From 0ef9c641b723ddc48db5ae5ccffe01a0c2636f55 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Fri, 17 Jan 2025 12:31:51 -0500 Subject: [PATCH] Permit 204/205 status codes on document requests as well --- integration/single-fetch-test.ts | 10 +++++++++- packages/react-router/lib/server-runtime/server.ts | 14 +++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/integration/single-fetch-test.ts b/integration/single-fetch-test.ts index 69b565bb16..e51b65a98a 100644 --- a/integration/single-fetch-test.ts +++ b/integration/single-fetch-test.ts @@ -1700,7 +1700,7 @@ test.describe("single-fetch", () => { ]); }); - test("does not try to encode a turbo-stream body into 204 responses", async ({ + test.only("does not try to encode a turbo-stream body into 204 responses", async ({ page, }) => { let fixture = await createFixture({ @@ -1743,6 +1743,14 @@ test.describe("single-fetch", () => { } }); + // Document requests + let documentRes = await fixture.requestDocument("/?index", { + method: "post", + }); + expect(documentRes.status).toBe(204); + expect(await documentRes.text()).toBe(""); + + // Data requests await app.goto("/"); (await page.$("[data-submit]"))?.click(); await page.waitForSelector("[data-active]"); diff --git a/packages/react-router/lib/server-runtime/server.ts b/packages/react-router/lib/server-runtime/server.ts index 747557d725..d7c56af787 100644 --- a/packages/react-router/lib/server-runtime/server.ts +++ b/packages/react-router/lib/server-runtime/server.ts @@ -356,9 +356,17 @@ async function handleDocumentRequest( let headers = getDocumentHeaders(build, context); - // 304 responses should not have a body or a content-type - if (context.statusCode === 304) { - return new Response(null, { status: 304, headers }); + // Do not include a response body if the status code is one of these, + // otherwise `undici` will throw an error when constructing the Response: + // /~https://github.com/nodejs/undici/blob/bd98a6303e45d5e0d44192a93731b1defdb415f3/lib/web/fetch/response.js#L522-L528 + // + // Specs: + // https://datatracker.ietf.org/doc/html/rfc9110#name-204-no-content + // https://datatracker.ietf.org/doc/html/rfc9110#name-205-reset-content + // https://datatracker.ietf.org/doc/html/rfc9110#name-304-not-modified + let NO_BODY_STATUS_CODES = new Set([204, 205, 304]); + if (NO_BODY_STATUS_CODES.has(context.statusCode)) { + return new Response(null, { status: context.statusCode, headers }); } // Sanitize errors outside of development environments