Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scope single fetch headers calls to only loaded routes #9085

Merged
merged 3 commits into from Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
10 changes: 8 additions & 2 deletions packages/remix-server-runtime/headers.ts
Expand Up @@ -3,10 +3,12 @@ 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 {
debugger;
let boundaryIdx = context.errors
? context.matches.findIndex((m) => context.errors![m.route.id])
: -1;
Expand All @@ -15,6 +17,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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were no longer used

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