Skip to content

Commit e7c2d94

Browse files
authored
Revert "fix: normalize RSC server redirects (#15421)" (#15434)
This reverts commit b137cab.
1 parent e4b70d6 commit e7c2d94

5 files changed

Lines changed: 26 additions & 57 deletions

File tree

packages/react-router/.changes/unstable.normalize-rsc-server-redirects.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/react-router/__tests__/rsc/server-test.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,9 @@ import {
33
type RSCMatch,
44
type RSCRouteConfigEntry,
55
} from "../../lib/rsc/server.rsc";
6-
import { routeRSCServerRequest } from "../../lib/rsc/server.ssr";
76
import { URL_LIMIT } from "../../lib/dom/ssr/fog-of-war";
87

98
describe("RSC server", () => {
10-
test("normalizes redirect locations", async () => {
11-
let response = await routeRSCServerRequest({
12-
request: new Request("https://remix.run/"),
13-
serverResponse: new Response("RSC payload", { status: 202 }),
14-
createFromReadableStream: async () => ({
15-
type: "redirect",
16-
location: "//example/path?search=value#hash",
17-
status: 302,
18-
}),
19-
async renderHTML() {
20-
throw new Error("Unexpected HTML render");
21-
},
22-
});
23-
24-
expect(response.headers.get("Location")).toBe(
25-
"/example/path?search=value#hash",
26-
);
27-
});
28-
299
describe("manifest requests", () => {
3010
test("rejects manifest requests over the URL limit", async () => {
3111
let path = `/${"a".repeat(URL_LIMIT)}.manifest`;

packages/react-router/lib/rsc/browser.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import type {
2424
DataStrategyFunctionArgs,
2525
RouterContextProvider,
2626
} from "../router/utils";
27-
import { ErrorResponseImpl, createContext } from "../router/utils";
27+
import { ErrorResponseImpl, createContext, resolvePath } from "../router/utils";
28+
import { PROTOCOL_RELATIVE_URL_REGEX } from "../router/url";
2829
import type {
2930
DecodedSingleFetchResults,
3031
FetchAndDecodeFunction,
@@ -44,7 +45,6 @@ import { RSCRouterGlobalErrorBoundary } from "./errorBoundaries";
4445
import type { RouteModules } from "../dom/ssr/routeModules";
4546
import { populateRSCRouteModules } from "./route-modules";
4647
import { URL_LIMIT, getPathsWithAncestors } from "../dom/ssr/fog-of-war";
47-
import { normalizeRedirectLocation } from "./redirect";
4848

4949
const defaultManifestPath = "/__manifest";
5050

@@ -1111,6 +1111,15 @@ function isExternalLocation(location: string) {
11111111
return newLocation.origin !== window.location.origin;
11121112
}
11131113

1114+
function normalizeRedirectLocation(location: string): string {
1115+
if (PROTOCOL_RELATIVE_URL_REGEX.test(location)) {
1116+
let path = resolvePath(location);
1117+
return path.pathname + path.search + path.hash;
1118+
}
1119+
1120+
return location;
1121+
}
1122+
11141123
function cloneRoutes(routes: DataRouteObject[] | undefined): DataRouteObject[] {
11151124
if (!routes) return undefined as any;
11161125
return routes.map((route) => ({

packages/react-router/lib/rsc/redirect.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/react-router/lib/rsc/server.ssr.tsx

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
decodeRouteErrorResponseDigest,
1717
} from "../errors";
1818
import { escapeHtml } from "../dom/ssr/markup";
19-
import { normalizeRedirectLocation } from "./redirect";
2019

2120
const defaultManifestPath = "/__manifest";
2221

@@ -204,8 +203,7 @@ export async function routeRSCServerRequest({
204203
serverResponse.status === SINGLE_FETCH_REDIRECT_STATUS &&
205204
payload.type === "redirect"
206205
) {
207-
let location = normalizeRedirectLocation(payload.location);
208-
if (hasInvalidProtocol(location)) {
206+
if (hasInvalidProtocol(payload.location)) {
209207
throw new Error("Invalid redirect location");
210208
}
211209

@@ -214,7 +212,7 @@ export async function routeRSCServerRequest({
214212
headers.delete("Content-Length");
215213
headers.delete("Content-Type");
216214
headers.delete("X-Remix-Response");
217-
headers.set("Location", location);
215+
headers.set("Location", payload.location);
218216

219217
return new Response(serverResponseB?.body || "", {
220218
headers,
@@ -262,12 +260,11 @@ export async function routeRSCServerRequest({
262260
headers.set("Content-Type", "text/html; charset=utf-8");
263261

264262
if (renderRedirect) {
265-
let location = normalizeRedirectLocation(renderRedirect.location);
266-
if (hasInvalidProtocol(location)) {
263+
if (hasInvalidProtocol(renderRedirect.location)) {
267264
throw new Error("Invalid redirect location");
268265
}
269266

270-
headers.set("Location", location);
267+
headers.set("Location", renderRedirect.location);
271268
return new Response(html, {
272269
status: renderRedirect.status,
273270
headers,
@@ -277,14 +274,13 @@ export async function routeRSCServerRequest({
277274
const redirectTransform = new TransformStream({
278275
flush(controller) {
279276
if (renderRedirect) {
280-
let location = normalizeRedirectLocation(renderRedirect.location);
281-
if (hasInvalidProtocol(location)) {
277+
if (hasInvalidProtocol(renderRedirect.location)) {
282278
return;
283279
}
284280

285281
controller.enqueue(
286282
new TextEncoder().encode(
287-
`<meta http-equiv="refresh" content="0;url=${escapeHtml(location)}"/>`,
283+
`<meta http-equiv="refresh" content="0;url=${escapeHtml(renderRedirect.location)}"/>`,
288284
),
289285
);
290286
}
@@ -317,15 +313,14 @@ export async function routeRSCServerRequest({
317313
}
318314

319315
if (renderRedirect) {
320-
let location = normalizeRedirectLocation(renderRedirect.location);
321-
if (hasInvalidProtocol(location)) {
316+
if (hasInvalidProtocol(renderRedirect.location)) {
322317
throw new Error("Invalid redirect location");
323318
}
324319

325-
return new Response(`Redirect: ${location}`, {
320+
return new Response(`Redirect: ${renderRedirect.location}`, {
326321
status: renderRedirect.status,
327322
headers: {
328-
Location: location,
323+
Location: renderRedirect.location,
329324
},
330325
});
331326
}
@@ -410,12 +405,11 @@ export async function routeRSCServerRequest({
410405
headers.set("Content-Type", "text/html; charset=utf-8");
411406

412407
if (retryRedirect) {
413-
let location = normalizeRedirectLocation(retryRedirect.location);
414-
if (hasInvalidProtocol(location)) {
408+
if (hasInvalidProtocol(retryRedirect.location)) {
415409
throw new Error("Invalid redirect location");
416410
}
417411

418-
headers.set("Location", location);
412+
headers.set("Location", retryRedirect.location);
419413
return new Response(html, {
420414
status: retryRedirect.status,
421415
headers,
@@ -425,14 +419,13 @@ export async function routeRSCServerRequest({
425419
const retryRedirectTransform = new TransformStream({
426420
flush(controller) {
427421
if (retryRedirect) {
428-
let location = normalizeRedirectLocation(retryRedirect.location);
429-
if (hasInvalidProtocol(location)) {
422+
if (hasInvalidProtocol(retryRedirect.location)) {
430423
return;
431424
}
432425

433426
controller.enqueue(
434427
new TextEncoder().encode(
435-
`<meta http-equiv="refresh" content="0;url=${escapeHtml(location)}"/>`,
428+
`<meta http-equiv="refresh" content="0;url=${escapeHtml(retryRedirect.location)}"/>`,
436429
),
437430
);
438431
}
@@ -527,15 +520,14 @@ export function RSCStaticRouter({ getPayload }: RSCStaticRouterProps) {
527520
const payload = useSafe(decoded);
528521

529522
if (payload.type === "redirect") {
530-
let location = normalizeRedirectLocation(payload.location);
531-
if (hasInvalidProtocol(location)) {
523+
if (hasInvalidProtocol(payload.location)) {
532524
throw new Error("Invalid redirect location");
533525
}
534526

535527
throw new Response(null, {
536528
status: payload.status,
537529
headers: {
538-
Location: location,
530+
Location: payload.location,
539531
},
540532
});
541533
}

0 commit comments

Comments
 (0)