fix: signature header request

This commit is contained in:
2026-08-16 14:12:46 +07:00
parent ffe9269bb5
commit e45c5bcabd
2 changed files with 16 additions and 0 deletions
+6
View File
@@ -64,6 +64,12 @@ async function createCanonicalRequest(request: Request, isQueryAuth: boolean): P
if (port && !((url.protocol === "https:" && port === "443") || (url.protocol === "http:" && port === "80"))) { if (port && !((url.protocol === "https:" && port === "443") || (url.protocol === "http:" && port === "80"))) {
headerValue += `:${port}`; headerValue += `:${port}`;
} }
} else if (headerName === "accept-encoding") {
// Cloudflare's edge rewrites the incoming Accept-Encoding value before the Worker
// sees it, so the literal value can never be recovered here. S3 SDKs that sign this
// header (aws-sdk-go, used by rclone/mc) always set it to "identity" beforehand, since
// S3 doesn't support transparent content-encoding on object bodies.
headerValue = "identity";
} else { } else {
headerValue = request.headers.get(headerName)?.trim() ?? ""; headerValue = request.headers.get(headerName)?.trim() ?? "";
} }
+10
View File
@@ -215,6 +215,16 @@ describe("S3 compatibility", () => {
expect(await missing.text()).toContain("<Code>NoSuchKey</Code>"); expect(await missing.text()).toContain("<Code>NoSuchKey</Code>");
}); });
it("verifies signatures that include Accept-Encoding even when the delivered value differs (Cloudflare rewrites it in transit)", async () => {
const original = await signed("/test-bucket/ae.txt", { method: "PUT", body: "hello", headers: { "accept-encoding": "identity" } });
const rewrittenHeaders = new Headers(original.headers);
rewrittenHeaders.set("accept-encoding", "gzip, deflate, br");
const mutated = new Request(original, { headers: rewrittenHeaders });
const response = await worker.fetch(mutated, ENV, CTX);
expect(response.status).toBe(200);
});
it("decodes both aws-chunked framing variants across arbitrary boundaries", async () => { it("decodes both aws-chunked framing variants across arbitrary boundaries", async () => {
const payload = bytes(70_013); const payload = bytes(70_013);
for (const trailer of [true, false]) { for (const trailer of [true, false]) {