Skip to content

Commit

Permalink
fix: handle net new redirects created by handleDataRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Mar 21, 2024
1 parent 283df54 commit fc1ec61
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-frogs-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/server-runtime": patch
---

handle net new redirects created by handleDataRequest
40 changes: 40 additions & 0 deletions packages/remix-server-runtime/__tests__/server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,46 @@ describe("shared server runtime", () => {
expect(indexAction.mock.calls.length).toBe(1);
});

test("data request handleDataRequest redirects are handled", async () => {
let rootLoader = jest.fn(() => {
return "root";
});
let indexLoader = jest.fn(() => {
return "index";
});
let build = mockServerBuild({
root: {
default: {},
loader: rootLoader,
},
"routes/_index": {
parentId: "root",
loader: indexLoader,
index: true,
},
});
build.entry.module.handleDataRequest.mockImplementation(async () => {
return new Response(null, {
status: 302,
headers: {
Location: "/redirect",
},
});
});
let handler = createRequestHandler(build, ServerMode.Test);

let request = new Request(`${baseUrl}/?_data=routes/_index`, {
method: "get",
});

let result = await handler(request);
expect(result.status).toBe(204);
expect(result.headers.get("X-Remix-Redirect")).toBe("/redirect");
expect(result.headers.get("X-Remix-Status")).toBe("302");
expect(rootLoader.mock.calls.length).toBe(0);
expect(indexLoader.mock.calls.length).toBe(1);
});

test("aborts request", async () => {
let rootLoader = jest.fn(() => {
return "root";
Expand Down
55 changes: 34 additions & 21 deletions packages/remix-server-runtime/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ export const createRequestHandler: CreateRequestHandlerFunction = (
params,
request,
});

if (isRedirectResponse(response)) {
response = createRemixRedirectResponse(response, _build.basename);
}
}
} else if (
_build.future.unstable_singleFetch &&
Expand Down Expand Up @@ -184,6 +188,10 @@ export const createRequestHandler: CreateRequestHandlerFunction = (
params,
request,
});

if (isRedirectResponse(response)) {
response = createRemixRedirectResponse(response, _build.basename);
}
}
} else if (
matches &&
Expand Down Expand Up @@ -243,27 +251,7 @@ async function handleDataRequest(
});

if (isRedirectResponse(response)) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location")!;
headers.set(
"X-Remix-Redirect",
build.basename
? stripBasename(redirectUrl, build.basename) || redirectUrl
: redirectUrl
);
headers.set("X-Remix-Status", response.status);
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}

return new Response(null, {
status: 204,
headers,
});
return createRemixRedirectResponse(response, build.basename);
}

if (DEFERRED_SYMBOL in response) {
Expand Down Expand Up @@ -850,3 +838,28 @@ function encodeViaTurboStream(
],
});
}

function createRemixRedirectResponse(
response: Response,
basename: string | undefined
) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location")!;
headers.set(
"X-Remix-Redirect",
basename ? stripBasename(redirectUrl, basename) || redirectUrl : redirectUrl
);
headers.set("X-Remix-Status", String(response.status));
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}

return new Response(null, {
status: 204,
headers,
});
}

0 comments on commit fc1ec61

Please sign in to comment.