Skip to content

Commit

Permalink
Scope single fetch headers calls to only loaded routes (#9085)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Mar 19, 2024
1 parent 00928fd commit 3523ae5
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 7 deletions.
110 changes: 109 additions & 1 deletion integration/single-fetch-test.ts
Expand Up @@ -416,7 +416,7 @@ test.describe("single-fetch", () => {
expect(urls).toEqual([]);
});

test("returns loader headers through the headers function", async () => {
test("handles headers correctly for loader and action calls", async () => {
let fixture = await createFixture({
config: {
future: {
Expand Down Expand Up @@ -476,6 +476,114 @@ test.describe("single-fetch", () => {
expect(res.headers.get("x-headers-function")).toEqual(null);
});

test("scopes loader headers to the _routes param if present", async () => {
let fixture = await createFixture({
config: {
future: {
unstable_singleFetch: true,
},
},
files: {
...files,
"app/routes/a.tsx": js`
export function headers({ loaderHeaders }) {
let headers = new Headers(loaderHeaders);
headers.set('x-a-headers', 'true')
return headers;
}
export function loader({ request }) {
return new Response(null, { headers: { "x-a-loader": "true" } });
}
export default function Comp() {
return null;
}
`,
"app/routes/a.b.tsx": js`
export function headers({ loaderHeaders, parentHeaders }) {
let headers = new Headers(parentHeaders);
loaderHeaders.forEach((value, name) => headers.set(name, value));
headers.set('x-b-headers', 'true')
return headers;
}
export function loader({ request }) {
return new Response(null, { headers: { "x-b-loader": "true" } });
}
export default function Comp() {
return null;
}
`,
"app/routes/a.b.c.tsx": js`
export function headers({ loaderHeaders, parentHeaders }) {
let headers = new Headers(parentHeaders);
loaderHeaders.forEach((value, name) => headers.set(name, value));
headers.set('x-c-headers', 'true')
return headers;
}
export function loader({ request }) {
return new Response(null, { headers: { "x-c-loader": "true" } });
}
export default function Comp() {
return null;
}
`,
},
});

let res = await fixture.requestSingleFetchData("/a/b/c.data");
expect(res.headers.get("x-a-loader")).toEqual("true");
expect(res.headers.get("x-a-headers")).toEqual("true");
expect(res.headers.get("x-b-loader")).toEqual("true");
expect(res.headers.get("x-b-headers")).toEqual("true");
expect(res.headers.get("x-c-loader")).toEqual("true");
expect(res.headers.get("x-c-headers")).toEqual("true");

res = await fixture.requestSingleFetchData(
"/a/b/c.data?_routes=routes%2Fa,routes%2Fa.b"
);
expect(res.headers.get("x-a-loader")).toEqual("true");
expect(res.headers.get("x-a-headers")).toEqual("true");
expect(res.headers.get("x-b-loader")).toEqual("true");
expect(res.headers.get("x-b-headers")).toEqual("true");
expect(res.headers.get("x-c-loader")).toBeNull();
expect(res.headers.get("x-c-headers")).toBeNull();

res = await fixture.requestSingleFetchData(
"/a/b/c.data?_routes=routes%2Fa"
);
expect(res.headers.get("x-a-loader")).toEqual("true");
expect(res.headers.get("x-a-headers")).toEqual("true");
expect(res.headers.get("x-b-loader")).toBeNull();
expect(res.headers.get("x-b-headers")).toBeNull();
expect(res.headers.get("x-c-loader")).toBeNull();
expect(res.headers.get("x-c-headers")).toBeNull();

res = await fixture.requestSingleFetchData(
"/a/b/c.data?_routes=routes%2Fa.b.c"
);
expect(res.headers.get("x-a-loader")).toBeNull();
expect(res.headers.get("x-a-headers")).toBeNull();
expect(res.headers.get("x-b-loader")).toBeNull();
expect(res.headers.get("x-b-headers")).toBeNull();
expect(res.headers.get("x-c-loader")).toEqual("true");
expect(res.headers.get("x-c-headers")).toEqual("true");

res = await fixture.requestSingleFetchData(
"/a/b/c.data?_routes=routes%2Fa,routes%2Fa.b.c"
);
expect(res.headers.get("x-a-loader")).toEqual("true");
expect(res.headers.get("x-a-loader")).toEqual("true");
expect(res.headers.get("x-b-headers")).toBeNull();
expect(res.headers.get("x-b-headers")).toBeNull();
expect(res.headers.get("x-c-loader")).toEqual("true");
expect(res.headers.get("x-c-headers")).toEqual("true");
});

test.describe("client loaders", () => {
test("when no routes have client loaders", async ({ page }) => {
let fixture = await createFixture(
Expand Down
9 changes: 7 additions & 2 deletions packages/remix-server-runtime/headers.ts
Expand Up @@ -3,9 +3,10 @@ import { splitCookiesString } from "set-cookie-parser";

import type { ServerBuild } from "./build";

export function getDocumentHeadersRR(
export function getDocumentHeaders(
build: ServerBuild,
context: StaticHandlerContext
context: StaticHandlerContext,
loadRouteIds?: string[]
): Headers {
let boundaryIdx = context.errors
? context.matches.findIndex((m) => context.errors![m.route.id])
Expand All @@ -15,6 +16,10 @@ export function getDocumentHeadersRR(
? context.matches.slice(0, boundaryIdx + 1)
: context.matches;

if (loadRouteIds) {
matches = matches.filter((m) => loadRouteIds.includes(m.route.id));
}

let errorHeaders: Headers | undefined;

if (boundaryIdx >= 0) {
Expand Down
6 changes: 2 additions & 4 deletions packages/remix-server-runtime/server.ts
Expand Up @@ -24,7 +24,7 @@ import {
serializeError,
serializeErrors,
} from "./errors";
import { getDocumentHeadersRR as getDocumentHeaders } from "./headers";
import { getDocumentHeaders } from "./headers";
import invariant from "./invariant";
import { ServerMode, isServerMode } from "./mode";
import type { RouteMatch } from "./routeMatching";
Expand Down Expand Up @@ -353,7 +353,6 @@ async function handleSingleFetchRequest(
request,
handlerUrl,
staticHandler,
matches,
loadContext,
handleError,
serverMode,
Expand Down Expand Up @@ -447,7 +446,6 @@ async function singleFetchLoaders(
request: Request,
handlerUrl: URL,
staticHandler: StaticHandler,
matches: RouteMatch<ServerRoute>[] | null,
loadContext: AppLoadContext,
handleError: (err: unknown) => void,
serverMode: ServerMode,
Expand Down Expand Up @@ -509,7 +507,7 @@ async function singleFetchLoaders(

return {
result: results,
headers: getDocumentHeaders(build, context),
headers: getDocumentHeaders(build, context, loadRouteIds),
status: context.statusCode,
};
} catch (error: unknown) {
Expand Down

0 comments on commit 3523ae5

Please sign in to comment.