Skip to content

Commit df78a29

Browse files
authored
Revert "fix: normalize control characters in relative URLs (#15422)" (#15441)
This reverts commit d1a4b1d.
1 parent d1a4b1d commit df78a29

10 files changed

Lines changed: 10 additions & 84 deletions

File tree

packages/react-router/.changes/patch.normalize-url-control-characters.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/react-router/__tests__/dom/link-href-test.tsx

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,26 +129,6 @@ describe("<Link> href", () => {
129129
expect(renderer.root.findByType("a").props.href).toEqual("//remix.run");
130130
});
131131

132-
test("normalizes special characters in relative <Link> values", () => {
133-
let renderer: TestRenderer.ReactTestRenderer;
134-
TestRenderer.act(() => {
135-
renderer = TestRenderer.create(
136-
<MemoryRouter initialEntries={["/inbox/messages"]}>
137-
<Routes>
138-
<Route path="inbox">
139-
<Route
140-
path="messages"
141-
element={<Link to={"/\t/nested/path"} />}
142-
/>
143-
</Route>
144-
</Routes>
145-
</MemoryRouter>,
146-
);
147-
});
148-
149-
expect(renderer.root.findByType("a").props.href).toEqual("/nested/path");
150-
});
151-
152132
test('<Link to="mailto:remix@example.com"> is treated as external link', () => {
153133
let renderer: TestRenderer.ReactTestRenderer;
154134
TestRenderer.act(() => {

packages/react-router/__tests__/router/browser-test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ describe("a browser history", () => {
4848
expect(href).toEqual("/the/path?the=query#the-hash");
4949
});
5050

51-
it("normalizes special characters in relative hrefs", () => {
52-
for (let char of ["\t", "\n", "\r"]) {
53-
expect(history.createHref(`/${char}/nested/path`)).toBe("/nested/path");
54-
}
55-
});
56-
5751
it("does not encode the generated path", () => {
5852
const encodedHref = history.createHref({
5953
pathname: "/%23abc",

packages/react-router/__tests__/router/redirects-test.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createMemoryHistory } from "../../lib/router/history";
22
import { IDLE_NAVIGATION, createRouter } from "../../lib/router/router";
3-
import { redirect, replace } from "../../lib/router/utils";
3+
import { replace } from "../../lib/router/utils";
44
import type { TestRouteObject } from "./utils/data-router-setup";
55
import { cleanup, setup } from "./utils/data-router-setup";
66
import { createFormData, tick } from "./utils/utils";
@@ -482,25 +482,6 @@ describe("redirects", () => {
482482
}
483483
});
484484

485-
it("normalizes special characters in redirects", async () => {
486-
let router = createRouter({
487-
history: createMemoryHistory(),
488-
routes: [
489-
{ path: "/" },
490-
{ path: "/start", loader: () => redirect("/\t/parent") },
491-
{ path: "/parent" },
492-
],
493-
});
494-
router.initialize();
495-
await tick();
496-
497-
await router.navigate("/start");
498-
expect(router.state.location).toMatchObject({
499-
pathname: "/parent",
500-
});
501-
router.dispose();
502-
});
503-
504485
it("properly handles same-origin absolute URLs when using a basename", async () => {
505486
let t = setup({ routes: REDIRECT_ROUTES, basename: "/base" });
506487

packages/react-router/lib/dom/lib.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ import type {
3737
import {
3838
ErrorResponseImpl,
3939
SUPPORTED_ERROR_TYPES,
40-
isAbsoluteUrl,
4140
joinPaths,
4241
matchPath,
4342
parseToInfo,
4443
resolveTo,
4544
stripBasename,
4645
} from "../router/utils";
46+
import { ABSOLUTE_URL_REGEX } from "../router/url";
4747

4848
// eslint-disable-next-line @typescript-eslint/no-unused-vars
4949
import type * as _ from "./global";
@@ -1341,7 +1341,7 @@ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
13411341
) {
13421342
let { basename, navigator, useTransitions } =
13431343
React.useContext(NavigationContext);
1344-
let isAbsolute = typeof to === "string" && isAbsoluteUrl(to);
1344+
let isAbsolute = typeof to === "string" && ABSOLUTE_URL_REGEX.test(to);
13451345

13461346
let parsed = parseToInfo(to, basename);
13471347
to = parsed.to;
@@ -1957,7 +1957,8 @@ export const Form = React.forwardRef<HTMLFormElement, FormProps>(
19571957
let formAction = useFormAction(action, { relative });
19581958
let formMethod: HTMLFormMethod =
19591959
method.toLowerCase() === "get" ? "get" : "post";
1960-
let isAbsolute = typeof action === "string" && isAbsoluteUrl(action);
1960+
let isAbsolute =
1961+
typeof action === "string" && ABSOLUTE_URL_REGEX.test(action);
19611962

19621963
let submitHandler: React.FormEventHandler<HTMLFormElement> = (event) => {
19631964
onSubmit && onSubmit(event);

packages/react-router/lib/dom/server.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
convertRoutesToDataRoutes,
3131
isRouteErrorResponse,
3232
} from "../router/utils";
33-
import { ABSOLUTE_URL_REGEX, normalizeRelativeUrl } from "../router/url";
33+
import { ABSOLUTE_URL_REGEX } from "../router/url";
3434
import { DataRoutes, Router, mapRouteProperties } from "../components";
3535
import {
3636
DataRouterContext,
@@ -511,7 +511,6 @@ function createHref(to: To) {
511511

512512
function encodeLocation(to: To): Path {
513513
let href = typeof to === "string" ? to : createPath(to);
514-
href = normalizeRelativeUrl(href);
515514
// Treating this as a full URL will strip any trailing spaces so we need to
516515
// pre-encode them since they might be part of a matching splat param from
517516
// an ancestor route

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { normalizeRelativeUrl, PROTOCOL_RELATIVE_URL_REGEX } from "./url";
1+
import { PROTOCOL_RELATIVE_URL_REGEX } from "./url";
22

33
////////////////////////////////////////////////////////////////////////////////
44
//#region Types and Constants
@@ -407,7 +407,7 @@ export function createBrowserHistory(
407407
}
408408

409409
function createBrowserHref(window: Window, to: To) {
410-
return normalizeRelativeUrl(typeof to === "string" ? to : createPath(to));
410+
return typeof to === "string" ? to : createPath(to);
411411
}
412412

413413
return getUrlBasedHistory(
@@ -795,7 +795,6 @@ export function createBrowserURLImpl(
795795
invariant(base, "No window.location.(origin|href) available to create URL");
796796

797797
let href = typeof to === "string" ? to : createPath(to);
798-
href = normalizeRelativeUrl(href);
799798

800799
// Treating this as a full URL will strip any trailing spaces so we need to
801800
// pre-encode them since they might be part of a matching splat param from

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ import {
7373
} from "./utils";
7474
import {
7575
normalizeProtocolRelativeUrl,
76-
normalizeRelativeUrl,
7776
PROTOCOL_RELATIVE_URL_REGEX,
7877
} from "./url";
7978

@@ -6850,8 +6849,6 @@ function normalizeRedirectLocation(
68506849
basename: string,
68516850
historyInstance: History,
68526851
): string {
6853-
location = normalizeRelativeUrl(location);
6854-
68556852
if (isAbsoluteUrl(location)) {
68566853
// Strip off the protocol+origin for same-origin + same-basename absolute redirects
68576854
let normalizedLocation = location;
Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,6 @@
11
export const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i;
22
export const PROTOCOL_RELATIVE_URL_REGEX = /^[\\/]{2}/;
33

4-
// Normalize characters ignored by the URL parser before determining whether a
5-
// URL is relative or absolute.
6-
export function normalizeRelativeUrl(url: string): string {
7-
if (ABSOLUTE_URL_REGEX.test(url)) {
8-
return url;
9-
}
10-
11-
let normalized = url.replace(/[\t\n\r]/g, "");
12-
if (!ABSOLUTE_URL_REGEX.test(normalized)) {
13-
return normalized;
14-
}
15-
16-
if (PROTOCOL_RELATIVE_URL_REGEX.test(normalized)) {
17-
return normalized.replace(/^[\\/]+/, "/");
18-
}
19-
20-
return normalized.replace(/^([a-z][a-z0-9+.-]*):/i, "$1%3A");
21-
}
22-
234
export function normalizeProtocolRelativeUrl(url: string, protocol: string) {
245
return protocol + url.replace(/\\/g, "/");
256
}

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { invariant, parsePath, warning } from "./history";
66
import {
77
ABSOLUTE_URL_REGEX,
88
normalizeProtocolRelativeUrl,
9-
normalizeRelativeUrl,
109
PROTOCOL_RELATIVE_URL_REGEX,
1110
} from "./url";
1211

@@ -1747,8 +1746,7 @@ export function prependBasename({
17471746
return pathname === "/" ? basename : joinPaths([basename, pathname]);
17481747
}
17491748

1750-
export const isAbsoluteUrl = (url: string) =>
1751-
ABSOLUTE_URL_REGEX.test(normalizeRelativeUrl(url));
1749+
export const isAbsoluteUrl = (url: string) => ABSOLUTE_URL_REGEX.test(url);
17521750

17531751
/**
17541752
* Returns a resolved {@link Path} object relative to the given pathname.
@@ -1769,7 +1767,6 @@ export function resolvePath(to: To, fromPathname = "/"): Path {
17691767

17701768
let pathname: string;
17711769
if (toPathname) {
1772-
toPathname = normalizeRelativeUrl(toPathname);
17731770
toPathname = removeDoubleSlashes(toPathname);
17741771
if (toPathname.startsWith("/")) {
17751772
pathname = resolvePathname(toPathname.substring(1), "/");
@@ -2266,9 +2263,7 @@ export function parseToInfo<T extends To | string>(
22662263
_to: T,
22672264
basename: string,
22682265
): ParsedLocationInfo<T | string> {
2269-
let to = (
2270-
typeof _to === "string" ? normalizeRelativeUrl(_to) : _to
2271-
) as string;
2266+
let to = _to as string;
22722267
if (typeof to !== "string" || !ABSOLUTE_URL_REGEX.test(to)) {
22732268
return {
22742269
absoluteURL: undefined,

0 commit comments

Comments
 (0)