Skip to content

Commit 2ab24cc

Browse files
authored
Add defensiveless for malformed hash urls without a leading slash (#10753)
1 parent 4bdd6b4 commit 2ab24cc

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

.changeset/hash-leading-slash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/router": patch
3+
---
4+
5+
Ensure hash history always includes a leading slash on hash pathnames

packages/router/__tests__/hash-test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,22 @@ describe("a hash history", () => {
6565
expect(unencodedHref).toEqual("#/#abc");
6666
});
6767

68+
it("prefixes raw hash values with /", () => {
69+
dom.window.history.replaceState(null, "", "#hello");
70+
history = createHashHistory({ window: dom.window as unknown as Window });
71+
expect(history.location.pathname).toBe("/hello");
72+
73+
history.push("world");
74+
expect(history.location.pathname).toBe("/world");
75+
76+
// Not supported but ensure we don't prefix here
77+
history.push("./relative");
78+
expect(history.location.pathname).toBe("./relative");
79+
80+
history.push("../relative");
81+
expect(history.location.pathname).toBe("../relative");
82+
});
83+
6884
describe("listen", () => {
6985
it("does not immediately call listeners", () => {
7086
Listen(history);

packages/router/history.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,17 @@ export function createHashHistory(
423423
search = "",
424424
hash = "",
425425
} = parsePath(window.location.hash.substr(1));
426+
427+
// Hash URL should always have a leading / just like window.location.pathname
428+
// does, so if an app ends up at a route like /#something then we add a
429+
// leading slash so all of our path-matching behaves the same as if it would
430+
// in a browser router. This is particularly important when there exists a
431+
// root splat route (<Route path="*">) since that matches internally against
432+
// "/*" and we'd expect /#something to 404 in a hash router app.
433+
if (!pathname.startsWith("/") && !pathname.startsWith(".")) {
434+
pathname = "/" + pathname;
435+
}
436+
426437
return createLocation(
427438
"",
428439
{ pathname, search, hash },

0 commit comments

Comments
 (0)