diff --git a/.changeset/slow-socks-juggle.md b/.changeset/slow-socks-juggle.md new file mode 100644 index 00000000000..8f7bc9cf626 --- /dev/null +++ b/.changeset/slow-socks-juggle.md @@ -0,0 +1,5 @@ +--- +"@remix-run/server-runtime": patch +--- + +Support 304 responses on document requests diff --git a/integration/single-fetch-test.ts b/integration/single-fetch-test.ts index 453ebe93db9..40a24fc0eb4 100644 --- a/integration/single-fetch-test.ts +++ b/integration/single-fetch-test.ts @@ -1925,8 +1925,23 @@ test.describe("single-fetch", () => { `, }, }); - let res = await fixture.requestSingleFetchData("/_root.data"); - expect(res.data).toEqual({ + + // Document requests + let documentRes = await fixture.requestDocument("/"); + let html = await documentRes.text(); + expect(html).toContain(""); + expect(html).toContain("

Hello from the loader!

"); + documentRes = await fixture.requestDocument("/", { + headers: { + "If-None-Match": "1234", + }, + }); + expect(documentRes.status).toBe(304); + expect(await documentRes.text()).toBe(""); + + // Data requests + let dataRes = await fixture.requestSingleFetchData("/_root.data"); + expect(dataRes.data).toEqual({ root: { data: { message: "ROOT", @@ -1938,13 +1953,13 @@ test.describe("single-fetch", () => { }, }, }); - res = await fixture.requestSingleFetchData("/_root.data", { + dataRes = await fixture.requestSingleFetchData("/_root.data", { headers: { "If-None-Match": "1234", }, }); - expect(res.status).toBe(304); - expect(res.data).toBeNull(); + expect(dataRes.status).toBe(304); + expect(dataRes.data).toBeNull(); }); test.describe("revalidations/_routes param", () => { diff --git a/packages/remix-server-runtime/server.ts b/packages/remix-server-runtime/server.ts index a28aff97369..14a7f680893 100644 --- a/packages/remix-server-runtime/server.ts +++ b/packages/remix-server-runtime/server.ts @@ -465,6 +465,11 @@ 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 }); + } + // Sanitize errors outside of development environments if (context.errors) { Object.values(context.errors).forEach((err) => {