Skip to content

Commit 7dc7f35

Browse files
authored
preserve search/hash in processed redirects (#9489)
* preserve search/hash in redirects * bundle bump
1 parent ea7351a commit 7dc7f35

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
},
108108
"filesize": {
109109
"packages/router/dist/router.js": {
110-
"none": "106 kB"
110+
"none": "108 kB"
111111
},
112112
"packages/react-router/dist/react-router.production.min.js": {
113113
"none": "12.5 kB"

packages/router/__tests__/router-test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5350,6 +5350,61 @@ describe("a router", () => {
53505350
errors: null,
53515351
});
53525352
});
5353+
5354+
it("preserves query and hash in redirects", async () => {
5355+
let t = setup({ routes: REDIRECT_ROUTES });
5356+
5357+
let nav1 = await t.fetch("/parent/child", {
5358+
formMethod: "post",
5359+
formData: createFormData({}),
5360+
});
5361+
5362+
let nav2 = await nav1.actions.child.redirectReturn(
5363+
"/parent?key=value#hash"
5364+
);
5365+
await nav2.loaders.parent.resolve("PARENT");
5366+
expect(t.router.state).toMatchObject({
5367+
location: {
5368+
pathname: "/parent",
5369+
search: "?key=value",
5370+
hash: "#hash",
5371+
},
5372+
navigation: IDLE_NAVIGATION,
5373+
loaderData: {
5374+
parent: "PARENT",
5375+
},
5376+
errors: null,
5377+
});
5378+
});
5379+
5380+
it("preserves query and hash in relative redirects", async () => {
5381+
let t = setup({ routes: REDIRECT_ROUTES });
5382+
5383+
let nav1 = await t.fetch("/parent/child", {
5384+
formMethod: "post",
5385+
formData: createFormData({}),
5386+
});
5387+
5388+
let nav2 = await nav1.actions.child.redirectReturn(
5389+
"..?key=value#hash",
5390+
undefined,
5391+
undefined,
5392+
["parent"]
5393+
);
5394+
await nav2.loaders.parent.resolve("PARENT");
5395+
expect(t.router.state).toMatchObject({
5396+
location: {
5397+
pathname: "/parent",
5398+
search: "?key=value",
5399+
hash: "#hash",
5400+
},
5401+
navigation: IDLE_NAVIGATION,
5402+
loaderData: {
5403+
parent: "PARENT",
5404+
},
5405+
errors: null,
5406+
});
5407+
});
53535408
});
53545409

53555410
describe("scroll restoration", () => {

packages/router/router.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2561,18 +2561,21 @@ async function callLoaderOrAction(
25612561
(match) => match.pathnameBase
25622562
);
25632563
let requestPath = createURL(request.url).pathname;
2564-
location = resolveTo(location, routePathnames, requestPath).pathname;
2564+
let resolvedLocation = resolveTo(location, routePathnames, requestPath);
25652565
invariant(
2566-
location,
2566+
createPath(resolvedLocation),
25672567
`Unable to resolve redirect location: ${result.headers.get("Location")}`
25682568
);
25692569

25702570
// Prepend the basename to the redirect location if we have one
25712571
if (basename) {
2572-
let path = createURL(location).pathname;
2573-
location = path === "/" ? basename : joinPaths([basename, path]);
2572+
let path = resolvedLocation.pathname;
2573+
resolvedLocation.pathname =
2574+
path === "/" ? basename : joinPaths([basename, path]);
25742575
}
25752576

2577+
location = createPath(resolvedLocation);
2578+
25762579
// Don't process redirects in the router during static requests requests.
25772580
// Instead, throw the Response and let the server handle it with an HTTP
25782581
// redirect. We also update the Location header in place in this flow so

0 commit comments

Comments
 (0)