Skip to content

Commit 3395030

Browse files
committed
Add console warning
1 parent c6a6e5d commit 3395030

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

packages/react-router/__tests__/resolvePath-test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,17 @@ describe("resolvePath", () => {
6666
});
6767

6868
it("normalizes any mid-path double-slashes", () => {
69+
let spy = jest.spyOn(console, "warn").mockImplementation(() => {});
70+
6971
expect(resolvePath("/search/../..//foo")).toMatchObject({
7072
pathname: "/foo",
7173
});
74+
7275
expect(resolvePath("search/../..//foo", "/inbox")).toMatchObject({
7376
pathname: "/foo",
7477
});
78+
79+
spy.mockRestore();
7580
});
7681

7782
it('ignores trailing slashes on the "from" pathname when resolving relative paths', () => {

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import {
5858
convertRoutesToDataRoutes,
5959
getPathContributingMatches,
6060
getResolveToMatches,
61+
isAbsoluteUrl,
6162
isUnsupportedLazyRouteObjectKey,
6263
isUnsupportedLazyRouteFunctionKey,
6364
isRouteErrorResponse,
@@ -838,9 +839,6 @@ export const IDLE_BLOCKER: BlockerUnblocked = {
838839
location: undefined,
839840
};
840841

841-
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
842-
export const isAbsoluteUrl = (url: string) => ABSOLUTE_URL_REGEX.test(url);
843-
844842
const defaultMapRouteProperties: MapRoutePropertiesFunction = (route) => ({
845843
hasErrorBoundary: Boolean(route.hasErrorBoundary),
846844
});

packages/react-router/lib/router/utils.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,9 @@ export function prependBasename({
15711571
return pathname === "/" ? basename : joinPaths([basename, pathname]);
15721572
}
15731573

1574+
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
1575+
export const isAbsoluteUrl = (url: string) => ABSOLUTE_URL_REGEX.test(url);
1576+
15741577
/**
15751578
* Returns a resolved {@link Path} object relative to the given pathname.
15761579
*
@@ -1590,11 +1593,18 @@ export function resolvePath(to: To, fromPathname = "/"): Path {
15901593

15911594
let pathname: string;
15921595
if (toPathname) {
1593-
if (toPathname.startsWith("//")) {
1596+
if (isAbsoluteUrl(toPathname)) {
15941597
pathname = toPathname;
15951598
} else {
1596-
// Normalize double-slashes
1597-
toPathname = toPathname.replace(/\/\/+/g, "/");
1599+
if (toPathname.includes("//")) {
1600+
let oldPathname = toPathname;
1601+
toPathname = toPathname.replace(/\/\/+/g, "/");
1602+
warning(
1603+
false,
1604+
`Pathnames cannot have embedded double slashes - normalizing ` +
1605+
`${oldPathname} -> ${toPathname}`,
1606+
);
1607+
}
15981608
if (toPathname.startsWith("/")) {
15991609
pathname = resolvePathname(toPathname.substring(1), "/");
16001610
} else {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
import { type Location } from "../router/history";
1313
import {
1414
createStaticHandler,
15-
isAbsoluteUrl,
1615
isMutationMethod,
1716
isResponse,
1817
isRedirectResponse,
@@ -26,6 +25,7 @@ import {
2625
type ShouldRevalidateFunction,
2726
type RouterContextProvider,
2827
type TrackedPromise,
28+
isAbsoluteUrl,
2929
isRouteErrorResponse,
3030
matchRoutes,
3131
prependBasename,

0 commit comments

Comments
 (0)