Skip to content

Commit

Permalink
Fail gracefully on invalid Link to values (#10367)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 committed Apr 21, 2023
1 parent bb799e7 commit 34779ab
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/invalid-link-to.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-router-dom": patch
---

Fail gracefully on `<Link to="//">` and other invalid URL values
20 changes: 20 additions & 0 deletions packages/react-router-dom/__tests__/link-href-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -907,4 +907,24 @@ describe("<Link> href", () => {
);
});
});

test("fails gracefully on invalid `to` values", () => {
let warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
let renderer: TestRenderer.ReactTestRenderer;
TestRenderer.act(() => {
renderer = TestRenderer.create(
<MemoryRouter>
<Routes>
<Route path="/" element={<Link to="//" />} />
</Routes>
</MemoryRouter>
);
});

expect(renderer.root.findByType("a").props.href).toEqual("//");
expect(warnSpy).toHaveBeenCalledWith(
'<Link to="//"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.'
);
warnSpy.mockRestore();
});
});
31 changes: 20 additions & 11 deletions packages/react-router-dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,17 +451,26 @@ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(

// Only check for external origins client-side
if (isBrowser) {
let currentUrl = new URL(window.location.href);
let targetUrl = to.startsWith("//")
? new URL(currentUrl.protocol + to)
: new URL(to);
let path = stripBasename(targetUrl.pathname, basename);

if (targetUrl.origin === currentUrl.origin && path != null) {
// Strip the protocol/origin/basename for same-origin absolute URLs
to = path + targetUrl.search + targetUrl.hash;
} else {
isExternal = true;
try {
let currentUrl = new URL(window.location.href);
let targetUrl = to.startsWith("//")
? new URL(currentUrl.protocol + to)
: new URL(to);
let path = stripBasename(targetUrl.pathname, basename);

if (targetUrl.origin === currentUrl.origin && path != null) {
// Strip the protocol/origin/basename for same-origin absolute URLs
to = path + targetUrl.search + targetUrl.hash;
} else {
isExternal = true;
}
} catch (e) {
// We can't do external URL detection without a valid URL
warning(
false,
`<Link to="${to}"> contains an invalid URL which will probably break ` +
`when clicked - please update to a valid URL path.`
);
}
}
}
Expand Down

0 comments on commit 34779ab

Please sign in to comment.