diff --git a/packages/react-router/__tests__/matchPath-test.tsx b/packages/react-router/__tests__/matchPath-test.tsx index 5d4a95b0aa..fb897ace8a 100644 --- a/packages/react-router/__tests__/matchPath-test.tsx +++ b/packages/react-router/__tests__/matchPath-test.tsx @@ -108,6 +108,14 @@ describe("matchPath", () => { pathnameBase: "/users/mj", }); }); + + it("matches second consecutive slash as a parameter", () => { + expect(matchPath("/:id", "//")).toMatchObject({ + params: { id: "/" }, + pathname: "//", + pathnameBase: "//", + }); + }); }); describe("with { end: false }", () => { @@ -164,6 +172,10 @@ describe("matchPath", () => { matchPath({ path: "/users/mj", end: false }, "/users/mj2") ).toBeNull(); }); + + it("does not match second consecutive slash as a parameter", () => { + expect(matchPath({ path: "/:id", end: false }, "//")).toBeNull(); + }); }); describe("with { end: false } and a / pattern", () => { diff --git a/packages/router/utils.ts b/packages/router/utils.ts index ef74175e35..d798b9edd7 100644 --- a/packages/router/utils.ts +++ b/packages/router/utils.ts @@ -902,6 +902,15 @@ export function matchPath< pattern = { path: pattern, caseSensitive: false, end: true }; } + // GH Issue #8072: Support matching against a standalone "/" as a parameter + // Here we encode the second slash to allow for pattern matching against the second slash. + // The encoded variant can be thought of as a placeholder during this matching process. + // When this process is complete we undo this encoding iff it was applied. + const encodeDoubleSlash = pattern.end && pathname.startsWith("//"); + if (encodeDoubleSlash) { + pathname = pathname.replace("//", "/%2F"); + } + let [matcher, compiledParams] = compilePath( pattern.path, pattern.caseSensitive, @@ -938,8 +947,8 @@ export function matchPath< return { params, - pathname: matchedPathname, - pathnameBase, + pathname: encodeDoubleSlash ? matchedPathname.replace("/%2F", "//") : matchedPathname, + pathnameBase: encodeDoubleSlash ? pathnameBase.replace("/%2F", "//") : pathnameBase, pattern, }; }