From 58f2624ed624b290f38fef75565dcedb7a8e0ce4 Mon Sep 17 00:00:00 2001 From: prompt.ac/@jeffrey Date: Thu, 30 Jul 2026 20:36:48 +0000 Subject: [PATCH] Honor signed Juke cloud upload headers --- juke-wizard/Sources/JukeWizard/JukeCloud.swift | 8 ++++++-- juke-wizard/bin/juke-cloud.mjs | 5 ++++- system/netlify/functions/juke-cloud.mjs | 6 +++++- 3 file(s) changed, 15 insertion(s)(+), 4 deletion(s)(-) diff --git a/juke-wizard/Sources/JukeWizard/JukeCloud.swift b/juke-wizard/Sources/JukeWizard/JukeCloud.swift --- a/juke-wizard/Sources/JukeWizard/JukeCloud.swift +++ b/juke-wizard/Sources/JukeWizard/JukeCloud.swift @@ -87,10 +87,14 @@ var upload = URLRequest(url: prepared.uploadURL) upload.httpMethod = "PUT" for (name, value) in prepared.headers { upload.setValue(value, forHTTPHeaderField: name) } upload.setValue(String(bytes), forHTTPHeaderField: "Content-Length") - let (_, response) = try await session.upload(for: upload, fromFile: file) + let (uploadData, response) = try await session.upload(for: upload, fromFile: file) let status = (response as? HTTPURLResponse)?.statusCode ?? 0 guard (200..<300).contains(status) else { - throw JukeCloudClientError.response("Upload failed (\(status)).") + let body = String(data: uploadData, encoding: .utf8) ?? "" + let detail = body.components(separatedBy: "").dropFirst().first? + .components(separatedBy: "").first + throw JukeCloudClientError.response( + "Upload failed (\(status))\(detail.map { ": \($0)" } ?? ".")") } return prepared.track } diff --git a/juke-wizard/bin/juke-cloud.mjs b/juke-wizard/bin/juke-cloud.mjs --- a/juke-wizard/bin/juke-cloud.mjs +++ b/juke-wizard/bin/juke-cloud.mjs @@ -63,7 +63,10 @@ headers: { ...prepared.headers, "Content-Length": String(stat.size) }, body: Readable.toWeb(createReadStream(absolute)), duplex: "half", }); - if (!response.ok) throw new Error(`Upload failed (${response.status})`); + if (!response.ok) { + const detail = (await response.text()).match(/([^<]+)<\/Message>/)?.[1]; + throw new Error(`Upload failed (${response.status})${detail ? `: ${detail}` : ""}`); + } return prepared.track; } diff --git a/system/netlify/functions/juke-cloud.mjs b/system/netlify/functions/juke-cloud.mjs --- a/system/netlify/functions/juke-cloud.mjs +++ b/system/netlify/functions/juke-cloud.mjs @@ -164,7 +164,11 @@ ContentDisposition: "inline", ACL: "public-read", }), { expiresIn: 15 * 60 }); const track = trackFromObject({ Key: key, Size: bytes, LastModified: new Date() }); - return respond(200, { uploadURL, headers: { "Content-Type": contentType }, track }); + return respond(200, { + uploadURL, + headers: { "Content-Type": contentType, "Content-Disposition": "inline" }, + track, + }); } catch (error) { console.error("juke-cloud failed", error?.message || error); return respond(503, { error: "Juke cloud is temporarily unavailable." }); -- tangled.sh