From 2db1ff7f98cd07aeb98d8f9064527b6f55a918ce Mon Sep 17 00:00:00 2001 From: Owen Smith Date: Mon, 7 Mar 2022 12:04:28 +0000 Subject: [PATCH] Remove "content-length: 0" from some requests, fixes #193 --- packages/core/src/standards/http.ts | 13 +++++++++++++ packages/core/test/standards/http.spec.ts | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/packages/core/src/standards/http.ts b/packages/core/src/standards/http.ts index 8ffaf26b9..6ba139a9d 100644 --- a/packages/core/src/standards/http.ts +++ b/packages/core/src/standards/http.ts @@ -700,6 +700,12 @@ const kDefaultHeadersToRemove = [ "user-agent", ]; +const methodsExpectingPayload = [ + "PUT", + "POST", + "PATCH" +]; + class MiniflareDispatcher extends Dispatcher { // dispatch, close & destroy are the only methods a Dispatcher must implement: // https://github.com/nodejs/undici/blob/09059fb491b4158a25981eb5598262b43a18c6ae/lib/dispatcher.js @@ -767,6 +773,13 @@ export async function fetch( req.headers.delete("cf-connecting-ip"); // Add "MF-Loop" header for loop detection req.headers.set(_kLoopHeader, String(ctx?.requestDepth ?? 1)); + // Delete "content-length: 0" from bodyless requests. Some proxies add this, + // but undici considers it an error. + // See https://github.com/cloudflare/miniflare/issues/193 + + if (!methodsExpectingPayload.includes(req.method) && req.headers.get("content-length") === "0") { + req.headers.delete("content-length"); + } // Mark default headers for removal that aren't explicitly included const removeHeaders: string[] = []; diff --git a/packages/core/test/standards/http.spec.ts b/packages/core/test/standards/http.spec.ts index baf00ec60..8c5f4dceb 100644 --- a/packages/core/test/standards/http.spec.ts +++ b/packages/core/test/standards/http.spec.ts @@ -960,6 +960,23 @@ test("fetch: removes Host and CF-Connecting-IP headers from Request", async (t) "x-real-ip": "127.0.0.1", }); }); +test("fetch: removes Content-Length 0 from body-less requests", async (t) => { + // Should remove content-length: 0 from certain methods because undici sees it + // as an error: https://github.com/cloudflare/miniflare/issues/193 + const upstream = ( + await useServer(t, (req, res) => res.end(JSON.stringify(req.headers))) + ).http; + const res = await fetch(upstream, { + method: "DELETE", + headers: { + "Content-Length": "0" + }, + }); + const headers = await res.json(); + t.like(headers, { + host: upstream.host, + }); +}); test("fetch: removes default fetch headers from Request unless explicitly added", async (t) => { // Should remove accept, accept-language, sec-fetch-mode, and user-agent // headers unless explicitly added: https://github.com/cloudflare/miniflare/issues/139