Skip to content

Commit 9941219

Browse files
authored
fix(playground-preview-worker,edge-preview-authenticated-proxy): ensure no body is passed when constructing a GET or HEAD request to the preview worker (#7793)
1 parent 5c02e46 commit 9941219

File tree

5 files changed

+69
-21
lines changed

5 files changed

+69
-21
lines changed

.changeset/clean-sheep-promise.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"edge-preview-authenticated-proxy": patch
3+
"playground-preview-worker": patch
4+
---
5+
6+
fix: ensure no body is passed when constructing a GET or HEAD request to the preview worker

packages/edge-preview-authenticated-proxy/src/index.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,12 @@ async function handleRawHttp(request: Request, url: URL) {
230230
}
231231
}
232232

233-
const workerResponse = await fetch(
234-
switchRemote(url, remote),
235-
new Request(request, {
236-
method,
237-
headers: requestHeaders,
238-
redirect: "manual",
239-
})
240-
);
233+
const workerResponse = await fetch(switchRemote(url, remote), {
234+
method,
235+
headers: requestHeaders,
236+
body: method === "GET" || method === "HEAD" ? null : request.body,
237+
redirect: "manual",
238+
});
241239

242240
const responseHeaders = new Headers(workerResponse.headers);
243241

packages/edge-preview-authenticated-proxy/tests/index.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,9 @@ describe("Raw HTTP preview", () => {
335335
return Response.redirect("https://example.com", 302)
336336
}
337337
if(url.pathname === "/method") {
338-
return new Response(request.method)
338+
return new Response(request.method, {
339+
headers: { "Test-Http-Method": request.method },
340+
})
339341
}
340342
if(url.pathname === "/status") {
341343
return new Response(407)
@@ -487,6 +489,30 @@ compatibility_date = "2023-01-01"
487489
expect(await resp.text()).toEqual("PUT");
488490
});
489491

492+
it.each(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"])(
493+
"should support %s method specified on the X-CF-Http-Method header",
494+
async (method) => {
495+
const token = randomBytes(4096).toString("hex");
496+
const resp = await worker.fetch(
497+
`https://0000.rawhttp.devprod.cloudflare.dev/method`,
498+
{
499+
method: "POST",
500+
headers: {
501+
origin: "https://cloudflare.dev",
502+
"X-CF-Token": token,
503+
"X-CF-Remote": `http://127.0.0.1:${remote.port}`,
504+
"X-CF-Http-Method": method,
505+
},
506+
}
507+
);
508+
509+
// HEAD request does not return any body. So we will confirm by asserting the response header
510+
expect(await resp.text()).toEqual(method === "HEAD" ? "" : method);
511+
// Header from the client response will be prefixed with "cf-ew-raw-"
512+
expect(resp.headers.get("cf-ew-raw-Test-Http-Method")).toEqual(method);
513+
}
514+
);
515+
490516
it("should fallback to the request method if the X-CF-Http-Method header is missing", async () => {
491517
const token = randomBytes(4096).toString("hex");
492518
const resp = await worker.fetch(

packages/playground-preview-worker/src/index.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,14 @@ async function handleRawHttp(request: Request, url: URL, env: Env) {
7979
}
8080
}
8181

82-
const workerResponse = await userObject.fetch(
83-
url,
84-
new Request(request, {
85-
method,
86-
headers: {
87-
...Object.fromEntries(headers),
88-
"cf-run-user-worker": "true",
89-
},
90-
redirect: "manual",
91-
})
92-
);
82+
headers.append("cf-run-user-worker", "true");
83+
84+
const workerResponse = await userObject.fetch(url, {
85+
method,
86+
headers,
87+
body: method === "GET" || method === "HEAD" ? null : request.body,
88+
redirect: "manual",
89+
});
9390

9491
const responseHeaders = new Headers(workerResponse.headers);
9592

packages/playground-preview-worker/tests/index.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ export default {
2424
return Response.redirect("https://example.com", 302)
2525
}
2626
if(url.pathname === "/method") {
27-
return new Response(request.method)
27+
return new Response(request.method, {
28+
headers: { "Test-Http-Method": request.method },
29+
})
2830
}
2931
if(url.pathname === "/status") {
3032
return new Response(407)
@@ -257,6 +259,25 @@ describe("Preview Worker", () => {
257259

258260
expect(await resp.text()).toEqual("PUT");
259261
});
262+
it.each(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"])(
263+
"should handle %s method specified on the X-CF-Http-Method header",
264+
async (method) => {
265+
const resp = await fetch(`${PREVIEW_REMOTE}/method`, {
266+
method: "POST",
267+
headers: {
268+
"X-CF-Token": defaultUserToken,
269+
"X-CF-Http-Method": method,
270+
"CF-Raw-HTTP": "true",
271+
},
272+
redirect: "manual",
273+
});
274+
275+
// HEAD request does not return any body. So we will confirm by asserting the response header
276+
expect(await resp.text()).toEqual(method === "HEAD" ? "" : method);
277+
// Header from the client response will be prefixed with "cf-ew-raw-"
278+
expect(resp.headers.get("cf-ew-raw-Test-Http-Method")).toEqual(method);
279+
}
280+
);
260281
it("should fallback to the request method if the X-CF-Http-Method header is missing", async () => {
261282
const resp = await fetch(`${PREVIEW_REMOTE}/method`, {
262283
method: "PUT",

0 commit comments

Comments
 (0)