1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-29 16:30:56 -05:00

fix(URL): IPv6 hostname support (#5766)

This commit is contained in:
Josh Byrnes 2020-06-11 04:05:10 +10:00 committed by GitHub
parent 1120dfe3f2
commit 408edbb065
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 3 deletions

View file

@ -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;
} }

View file

@ -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 {