Skip to content

Commit 3ea100c

Browse files
authored
fix(routing): normalize literal glob components through new URL() (#41682)
1 parent 142a273 commit 3ea100c

2 files changed

Lines changed: 14 additions & 0 deletions

File tree

packages/isomorphic/urlMatch.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ function resolveGlobBase(baseURL: string | undefined, match: string): string {
239239
// Preserve explicit schema as is as it may affect trailing slashes after domain.
240240
return token;
241241
}
242+
// Components without glob metacharacters are literal, so let them round-trip
243+
// through new URL() to preserve normalization (default ports such as :80/:443,
244+
// percent-encoding, IDN hosts). Only opaque tokens defeat that normalization.
245+
if (!/[*?{}\\]/.test(token))
246+
return token;
242247
const questionIndex = token.indexOf('?');
243248
if (questionIndex === -1)
244249
return mapToken(token, `$_${index}_$`);

tests/page/interception.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ it('should work with glob', async () => {
134134
expect(urlMatches(undefined, 'https://playwright.dev/foobar', 'https://playwright.dev/fooBAR')).toBeFalsy();
135135
expect(urlMatches(undefined, 'https://playwright.dev/foobar?a=b', 'https://playwright.dev/foobar?A=B')).toBeFalsy();
136136

137+
// Literal globs are normalized through new URL(), so explicit default ports,
138+
// percent-encoding and IDN hosts match request.url() which is already normalized.
139+
expect(urlMatches(undefined, 'http://example.com/path', 'http://example.com:80/path')).toBeTruthy();
140+
expect(urlMatches(undefined, 'https://example.com/path', 'https://example.com:443/path')).toBeTruthy();
141+
expect(urlMatches(undefined, 'http://example.com:8080/path', 'http://example.com:8080/path')).toBeTruthy();
142+
expect(urlMatches(undefined, 'http://localhost/', 'http://localhost:80/**')).toBeTruthy();
143+
expect(urlMatches(undefined, 'http://example.com/foo%20bar', 'http://example.com/foo bar')).toBeTruthy();
144+
expect(urlMatches(undefined, 'http://xn--mnchen-3ya.de/', 'http://münchen.de/')).toBeTruthy();
145+
137146
expect(urlMatches(undefined, 'https://localhost:3000/?a=b', '**/?a=b')).toBeTruthy();
138147
expect(urlMatches(undefined, 'https://localhost:3000/?a=b', '**?a=b')).toBeTruthy();
139148
expect(urlMatches(undefined, 'https://localhost:3000/?a=b', '**=b')).toBeTruthy();

0 commit comments

Comments
 (0)