Skip to content

Commit

Permalink
Fix single fetch redirects when a basename is present
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Aug 9, 2024
1 parent cd403b5 commit 8ed5917
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-teachers-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/server-runtime": patch
---

Single Fetch: Fix redirects when a `basename` is presernt
67 changes: 67 additions & 0 deletions integration/single-fetch-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,73 @@ test.describe("single-fetch", () => {
expect(await app.getHtml("#target")).toContain("Target");
});

test.only("processes redirects when a basename is present", async ({
page,
}) => {
let fixture = await createFixture({
compiler: "vite",
files: {
...files,
"vite.config.ts": js`
import { defineConfig } from "vite";
import { vitePlugin as remix } from "@remix-run/dev";
export default defineConfig({
plugins: [
remix({
basename: '/base',
future: {
unstable_singleFetch: true,
}
}),
],
});
`,
"app/routes/data.tsx": js`
import { redirect } from '@remix-run/node';
export function loader() {
throw redirect('/target');
}
export default function Component() {
return null
}
`,
"app/routes/target.tsx": js`
export default function Component() {
return <h1 id="target">Target</h1>
}
`,
},
});

console.error = () => {};

let res = await fixture.requestDocument("/base/data");
expect(res.status).toBe(302);
expect(res.headers.get("Location")).toBe("/base/target");
expect(await res.text()).toBe("");

let { status, data } = await fixture.requestSingleFetchData(
"/base/data.data"
);
expect(data).toEqual({
[SingleFetchRedirectSymbol]: {
status: 302,
redirect: "/target",
reload: false,
replace: false,
revalidate: false,
},
});
expect(status).toBe(202);

let appFixture = await createAppFixture(fixture);
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/base/");
await app.clickLink("/base/data");
await page.waitForSelector("#target");
expect(await app.getHtml("#target")).toContain("Target");
});

test("processes thrown loader errors", async ({ page }) => {
let fixture = await createFixture({
config: {
Expand Down
31 changes: 25 additions & 6 deletions packages/remix-server-runtime/single-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
isRouteErrorResponse,
unstable_data as routerData,
UNSAFE_ErrorResponseImpl as ErrorResponseImpl,
stripBasename,
} from "@remix-run/router";
import { encode } from "turbo-stream";

Expand Down Expand Up @@ -110,8 +111,13 @@ export async function singleFetchAction(
// Unlike `handleDataRequest`, when singleFetch is enabled, query does
// let non-Response return values through
if (isResponse(result)) {
console.log("a");
return {
result: getSingleFetchRedirect(result.status, result.headers),
result: getSingleFetchRedirect(
result.status,
result.headers,
build.basename
),
headers: result.headers,
status: SINGLE_FETCH_REDIRECT_STATUS,
};
Expand All @@ -121,8 +127,13 @@ export async function singleFetchAction(
let headers = getDocumentHeaders(build, context);

if (isRedirectStatusCode(context.statusCode) && headers.has("Location")) {
console.log("b");
return {
result: getSingleFetchRedirect(context.statusCode, headers),
result: getSingleFetchRedirect(
context.statusCode,
headers,
build.basename
),
headers,
status: SINGLE_FETCH_REDIRECT_STATUS,
};
Expand Down Expand Up @@ -192,7 +203,8 @@ export async function singleFetchLoaders(
result: {
[SingleFetchRedirectSymbol]: getSingleFetchRedirect(
result.status,
result.headers
result.headers,
build.basename
),
},
headers: result.headers,
Expand All @@ -208,7 +220,8 @@ export async function singleFetchLoaders(
result: {
[SingleFetchRedirectSymbol]: getSingleFetchRedirect(
context.statusCode,
headers
headers,
build.basename
),
},
headers,
Expand Down Expand Up @@ -264,10 +277,16 @@ export async function singleFetchLoaders(

export function getSingleFetchRedirect(
status: number,
headers: Headers
headers: Headers,
basename: string | undefined
): SingleFetchRedirectResult {
let redirect = headers.get("Location")!;
if (basename) {
redirect = stripBasename(redirect, basename) || redirect;
headers.delete("Location");
}
return {
redirect: headers.get("Location")!,
redirect,
status,
revalidate:
// Technically X-Remix-Revalidate isn't needed here - that was an implementation
Expand Down

0 comments on commit 8ed5917

Please sign in to comment.