mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
fix(URL): IPv6 hostname support (#5766)
This commit is contained in:
parent
1120dfe3f2
commit
408edbb065
2 changed files with 32 additions and 3 deletions
|
@ -39,7 +39,7 @@ const MAX_PORT = 2 ** 16 - 1;
|
||||||
// (LHS). e.g.
|
// (LHS). e.g.
|
||||||
// takePattern("https://deno.land:80", /^([a-z]+):[/]{2}/)
|
// takePattern("https://deno.land:80", /^([a-z]+):[/]{2}/)
|
||||||
// = ["http", "deno.land:80"]
|
// = ["http", "deno.land:80"]
|
||||||
// takePattern("deno.land:80", /^([^:]+):)
|
// takePattern("deno.land:80", /^(\[[0-9a-fA-F.:]{2,}\]|[^:]+)/)
|
||||||
// = ["deno.land", "80"]
|
// = ["deno.land", "80"]
|
||||||
function takePattern(string: string, pattern: RegExp): [string, string] {
|
function takePattern(string: string, pattern: RegExp): [string, string] {
|
||||||
let capture = "";
|
let capture = "";
|
||||||
|
@ -80,7 +80,10 @@ function parse(url: string, isBase = true): URLParts | undefined {
|
||||||
parts.username = encodeUserinfo(parts.username);
|
parts.username = encodeUserinfo(parts.username);
|
||||||
[parts.password] = takePattern(restAuthentication, /^:(.*)/);
|
[parts.password] = takePattern(restAuthentication, /^:(.*)/);
|
||||||
parts.password = encodeUserinfo(parts.password);
|
parts.password = encodeUserinfo(parts.password);
|
||||||
[parts.hostname, restAuthority] = takePattern(restAuthority, /^([^:]+)/);
|
[parts.hostname, restAuthority] = takePattern(
|
||||||
|
restAuthority,
|
||||||
|
/^(\[[0-9a-fA-F.:]{2,}\]|[^:]+)/
|
||||||
|
);
|
||||||
[parts.port] = takePattern(restAuthority, /^:(.*)/);
|
[parts.port] = takePattern(restAuthority, /^:(.*)/);
|
||||||
if (!isValidPort(parts.port)) {
|
if (!isValidPort(parts.port)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -92,7 +95,11 @@ function parse(url: string, isBase = true): URLParts | undefined {
|
||||||
parts.port = "";
|
parts.port = "";
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
parts.hostname = encodeHostname(parts.hostname).toLowerCase();
|
const IPv6re = /^\[[0-9a-fA-F.:]{2,}\]$/;
|
||||||
|
if (!IPv6re.test(parts.hostname)) {
|
||||||
|
parts.hostname = encodeHostname(parts.hostname); // Non-IPv6 URLs
|
||||||
|
}
|
||||||
|
parts.hostname = parts.hostname.toLowerCase();
|
||||||
} catch {
|
} catch {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,28 @@ unitTest(function urlParsing(): void {
|
||||||
JSON.stringify({ key: url }),
|
JSON.stringify({ key: url }),
|
||||||
`{"key":"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"}`
|
`{"key":"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// IPv6 type hostname.
|
||||||
|
const urlv6 = new URL(
|
||||||
|
"https://foo:bar@[::1]:8000/qux/quux?foo=bar&baz=12#qat"
|
||||||
|
);
|
||||||
|
assertEquals(urlv6.origin, "https://[::1]:8000");
|
||||||
|
assertEquals(urlv6.password, "bar");
|
||||||
|
assertEquals(urlv6.pathname, "/qux/quux");
|
||||||
|
assertEquals(urlv6.port, "8000");
|
||||||
|
assertEquals(urlv6.protocol, "https:");
|
||||||
|
assertEquals(urlv6.search, "?foo=bar&baz=12");
|
||||||
|
assertEquals(urlv6.searchParams.getAll("foo"), ["bar"]);
|
||||||
|
assertEquals(urlv6.searchParams.getAll("baz"), ["12"]);
|
||||||
|
assertEquals(urlv6.username, "foo");
|
||||||
|
assertEquals(
|
||||||
|
String(urlv6),
|
||||||
|
"https://foo:bar@[::1]:8000/qux/quux?foo=bar&baz=12#qat"
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
JSON.stringify({ key: urlv6 }),
|
||||||
|
`{"key":"https://foo:bar@[::1]:8000/qux/quux?foo=bar&baz=12#qat"}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
unitTest(function urlModifications(): void {
|
unitTest(function urlModifications(): void {
|
||||||
|
|
Loading…
Reference in a new issue