mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
1078 lines
28 KiB
JavaScript
1078 lines
28 KiB
JavaScript
import { describe, test } from "bun:test";
|
|
import assert from "node:assert";
|
|
import url from "node:url";
|
|
import { inspect } from "node:util";
|
|
|
|
describe("url.parse then url.format", () => {
|
|
// URLs to parse, and expected data
|
|
// { URL : parsed }
|
|
const parseTests = {
|
|
"//some_path": {
|
|
href: "//some_path",
|
|
pathname: "//some_path",
|
|
path: "//some_path",
|
|
},
|
|
|
|
"http:\\\\evil-phisher\\foo.html#h\\a\\s\\h": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "evil-phisher",
|
|
hostname: "evil-phisher",
|
|
pathname: "/foo.html",
|
|
path: "/foo.html",
|
|
hash: "#h%5Ca%5Cs%5Ch",
|
|
href: "http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch",
|
|
},
|
|
|
|
'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "evil-phisher",
|
|
hostname: "evil-phisher",
|
|
pathname: "/foo.html",
|
|
search: "?json=%22%5C%22foo%5C%22%22",
|
|
query: "json=%22%5C%22foo%5C%22%22",
|
|
path: "/foo.html?json=%22%5C%22foo%5C%22%22",
|
|
hash: "#h%5Ca%5Cs%5Ch",
|
|
href: "http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch",
|
|
},
|
|
|
|
"http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "evil-phisher",
|
|
hostname: "evil-phisher",
|
|
pathname: "/foo.html",
|
|
path: "/foo.html",
|
|
hash: "#h%5Ca%5Cs%5Ch?blarg",
|
|
href: "http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg",
|
|
},
|
|
|
|
"http:\\\\evil-phisher\\foo.html": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "evil-phisher",
|
|
hostname: "evil-phisher",
|
|
pathname: "/foo.html",
|
|
path: "/foo.html",
|
|
href: "http://evil-phisher/foo.html",
|
|
},
|
|
|
|
"HTTP://www.example.com/": {
|
|
href: "http://www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"HTTP://www.example.com": {
|
|
href: "http://www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://www.ExAmPlE.com/": {
|
|
href: "http://www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://user:pw@www.ExAmPlE.com/": {
|
|
href: "http://user:pw@www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pw",
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://USER:PW@www.ExAmPlE.com/": {
|
|
href: "http://USER:PW@www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "USER:PW",
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://user@www.example.com/": {
|
|
href: "http://user@www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user",
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://user%3Apw@www.example.com/": {
|
|
href: "http://user:pw@www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pw",
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://x.com/path?that's#all, folks": {
|
|
href: "http://x.com/path?that%27s#all,%20folks",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x.com",
|
|
hostname: "x.com",
|
|
search: "?that%27s",
|
|
query: "that%27s",
|
|
pathname: "/path",
|
|
hash: "#all,%20folks",
|
|
path: "/path?that%27s",
|
|
},
|
|
|
|
"HTTP://X.COM/Y": {
|
|
href: "http://x.com/Y",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x.com",
|
|
hostname: "x.com",
|
|
pathname: "/Y",
|
|
path: "/Y",
|
|
},
|
|
|
|
// Whitespace in the front
|
|
" http://www.example.com/": {
|
|
href: "http://www.example.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.example.com",
|
|
hostname: "www.example.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
// + not an invalid host character
|
|
// per https://URL.spec.whatwg.org/#host-parsing
|
|
"http://x.y.com+a/b/c": {
|
|
href: "http://x.y.com+a/b/c",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x.y.com+a",
|
|
hostname: "x.y.com+a",
|
|
pathname: "/b/c",
|
|
path: "/b/c",
|
|
},
|
|
|
|
// An unexpected invalid char in the hostname.
|
|
"HtTp://x.y.cOm;a/b/c?d=e#f g<h>i": {
|
|
href: "http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x.y.com",
|
|
hostname: "x.y.com",
|
|
pathname: ";a/b/c",
|
|
search: "?d=e",
|
|
query: "d=e",
|
|
hash: "#f%20g%3Ch%3Ei",
|
|
path: ";a/b/c?d=e",
|
|
},
|
|
|
|
// Make sure that we don't accidentally lcast the path parts.
|
|
"HtTp://x.y.cOm;A/b/c?d=e#f g<h>i": {
|
|
href: "http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x.y.com",
|
|
hostname: "x.y.com",
|
|
pathname: ";A/b/c",
|
|
search: "?d=e",
|
|
query: "d=e",
|
|
hash: "#f%20g%3Ch%3Ei",
|
|
path: ";A/b/c?d=e",
|
|
},
|
|
|
|
"http://x...y...#p": {
|
|
href: "http://x...y.../#p",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x...y...",
|
|
hostname: "x...y...",
|
|
hash: "#p",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
'http://x/p/"quoted"': {
|
|
href: "http://x/p/%22quoted%22",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x",
|
|
hostname: "x",
|
|
pathname: "/p/%22quoted%22",
|
|
path: "/p/%22quoted%22",
|
|
},
|
|
|
|
"<http://goo.corn/bread> Is a URL!": {
|
|
href: "%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!",
|
|
pathname: "%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!",
|
|
path: "%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!",
|
|
},
|
|
|
|
"http://www.narwhaljs.org/blog/categories?id=news": {
|
|
href: "http://www.narwhaljs.org/blog/categories?id=news",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.narwhaljs.org",
|
|
hostname: "www.narwhaljs.org",
|
|
search: "?id=news",
|
|
query: "id=news",
|
|
pathname: "/blog/categories",
|
|
path: "/blog/categories?id=news",
|
|
},
|
|
|
|
"http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=": {
|
|
href: "http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "mt0.google.com",
|
|
hostname: "mt0.google.com",
|
|
pathname: "/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
path: "/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
},
|
|
|
|
"http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=": {
|
|
href: "http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api" + "&x=2&y=2&z=3&s=",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "mt0.google.com",
|
|
hostname: "mt0.google.com",
|
|
search: "???&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
query: "??&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
pathname: "/vt/lyrs=m@114",
|
|
path: "/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
},
|
|
|
|
"http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=": {
|
|
href: "http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "mt0.google.com",
|
|
auth: "user:pass",
|
|
hostname: "mt0.google.com",
|
|
search: "???&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
query: "??&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
pathname: "/vt/lyrs=m@114",
|
|
path: "/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=",
|
|
},
|
|
|
|
"file:///etc/passwd": {
|
|
href: "file:///etc/passwd",
|
|
slashes: true,
|
|
protocol: "file:",
|
|
pathname: "/etc/passwd",
|
|
hostname: "",
|
|
host: "",
|
|
path: "/etc/passwd",
|
|
},
|
|
|
|
"file://localhost/etc/passwd": {
|
|
href: "file://localhost/etc/passwd",
|
|
protocol: "file:",
|
|
slashes: true,
|
|
pathname: "/etc/passwd",
|
|
hostname: "localhost",
|
|
host: "localhost",
|
|
path: "/etc/passwd",
|
|
},
|
|
|
|
"file://foo/etc/passwd": {
|
|
href: "file://foo/etc/passwd",
|
|
protocol: "file:",
|
|
slashes: true,
|
|
pathname: "/etc/passwd",
|
|
hostname: "foo",
|
|
host: "foo",
|
|
path: "/etc/passwd",
|
|
},
|
|
|
|
"file:///etc/node/": {
|
|
href: "file:///etc/node/",
|
|
slashes: true,
|
|
protocol: "file:",
|
|
pathname: "/etc/node/",
|
|
hostname: "",
|
|
host: "",
|
|
path: "/etc/node/",
|
|
},
|
|
|
|
"file://localhost/etc/node/": {
|
|
href: "file://localhost/etc/node/",
|
|
protocol: "file:",
|
|
slashes: true,
|
|
pathname: "/etc/node/",
|
|
hostname: "localhost",
|
|
host: "localhost",
|
|
path: "/etc/node/",
|
|
},
|
|
|
|
"file://foo/etc/node/": {
|
|
href: "file://foo/etc/node/",
|
|
protocol: "file:",
|
|
slashes: true,
|
|
pathname: "/etc/node/",
|
|
hostname: "foo",
|
|
host: "foo",
|
|
path: "/etc/node/",
|
|
},
|
|
|
|
"http:/baz/../foo/bar": {
|
|
href: "http:/baz/../foo/bar",
|
|
protocol: "http:",
|
|
pathname: "/baz/../foo/bar",
|
|
path: "/baz/../foo/bar",
|
|
},
|
|
|
|
"http://user:pass@example.com:8000/foo/bar?baz=quux#frag": {
|
|
href: "http://user:pass@example.com:8000/foo/bar?baz=quux#frag",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.com:8000",
|
|
auth: "user:pass",
|
|
port: "8000",
|
|
hostname: "example.com",
|
|
hash: "#frag",
|
|
search: "?baz=quux",
|
|
query: "baz=quux",
|
|
pathname: "/foo/bar",
|
|
path: "/foo/bar?baz=quux",
|
|
},
|
|
|
|
"//user:pass@example.com:8000/foo/bar?baz=quux#frag": {
|
|
href: "//user:pass@example.com:8000/foo/bar?baz=quux#frag",
|
|
slashes: true,
|
|
host: "example.com:8000",
|
|
auth: "user:pass",
|
|
port: "8000",
|
|
hostname: "example.com",
|
|
hash: "#frag",
|
|
search: "?baz=quux",
|
|
query: "baz=quux",
|
|
pathname: "/foo/bar",
|
|
path: "/foo/bar?baz=quux",
|
|
},
|
|
|
|
"/foo/bar?baz=quux#frag": {
|
|
href: "/foo/bar?baz=quux#frag",
|
|
hash: "#frag",
|
|
search: "?baz=quux",
|
|
query: "baz=quux",
|
|
pathname: "/foo/bar",
|
|
path: "/foo/bar?baz=quux",
|
|
},
|
|
|
|
"http:/foo/bar?baz=quux#frag": {
|
|
href: "http:/foo/bar?baz=quux#frag",
|
|
protocol: "http:",
|
|
hash: "#frag",
|
|
search: "?baz=quux",
|
|
query: "baz=quux",
|
|
pathname: "/foo/bar",
|
|
path: "/foo/bar?baz=quux",
|
|
},
|
|
|
|
"mailto:foo@bar.com?subject=hello": {
|
|
href: "mailto:foo@bar.com?subject=hello",
|
|
protocol: "mailto:",
|
|
host: "bar.com",
|
|
auth: "foo",
|
|
hostname: "bar.com",
|
|
search: "?subject=hello",
|
|
query: "subject=hello",
|
|
path: "?subject=hello",
|
|
},
|
|
|
|
"javascript:alert('hello');": {
|
|
href: "javascript:alert('hello');",
|
|
protocol: "javascript:",
|
|
pathname: "alert('hello');",
|
|
path: "alert('hello');",
|
|
},
|
|
|
|
"xmpp:isaacschlueter@jabber.org": {
|
|
href: "xmpp:isaacschlueter@jabber.org",
|
|
protocol: "xmpp:",
|
|
host: "jabber.org",
|
|
auth: "isaacschlueter",
|
|
hostname: "jabber.org",
|
|
},
|
|
|
|
"http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar": {
|
|
href: "http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "127.0.0.1:8080",
|
|
auth: "atpass:foo@bar",
|
|
hostname: "127.0.0.1",
|
|
port: "8080",
|
|
pathname: "/path",
|
|
search: "?search=foo",
|
|
query: "search=foo",
|
|
hash: "#bar",
|
|
path: "/path?search=foo",
|
|
},
|
|
|
|
"svn+ssh://foo/bar": {
|
|
href: "svn+ssh://foo/bar",
|
|
host: "foo",
|
|
hostname: "foo",
|
|
protocol: "svn+ssh:",
|
|
pathname: "/bar",
|
|
path: "/bar",
|
|
slashes: true,
|
|
},
|
|
|
|
"dash-test://foo/bar": {
|
|
href: "dash-test://foo/bar",
|
|
host: "foo",
|
|
hostname: "foo",
|
|
protocol: "dash-test:",
|
|
pathname: "/bar",
|
|
path: "/bar",
|
|
slashes: true,
|
|
},
|
|
|
|
"dash-test:foo/bar": {
|
|
href: "dash-test:foo/bar",
|
|
host: "foo",
|
|
hostname: "foo",
|
|
protocol: "dash-test:",
|
|
pathname: "/bar",
|
|
path: "/bar",
|
|
},
|
|
|
|
"dot.test://foo/bar": {
|
|
href: "dot.test://foo/bar",
|
|
host: "foo",
|
|
hostname: "foo",
|
|
protocol: "dot.test:",
|
|
pathname: "/bar",
|
|
path: "/bar",
|
|
slashes: true,
|
|
},
|
|
|
|
"dot.test:foo/bar": {
|
|
href: "dot.test:foo/bar",
|
|
host: "foo",
|
|
hostname: "foo",
|
|
protocol: "dot.test:",
|
|
pathname: "/bar",
|
|
path: "/bar",
|
|
},
|
|
|
|
// IDNA tests
|
|
"http://www.日本語.com/": {
|
|
href: "http://www.xn--wgv71a119e.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.xn--wgv71a119e.com",
|
|
hostname: "www.xn--wgv71a119e.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://example.Bücher.com/": {
|
|
href: "http://example.xn--bcher-kva.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.xn--bcher-kva.com",
|
|
hostname: "example.xn--bcher-kva.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://www.Äffchen.com/": {
|
|
href: "http://www.xn--ffchen-9ta.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.xn--ffchen-9ta.com",
|
|
hostname: "www.xn--ffchen-9ta.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i": {
|
|
href: "http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "www.xn--ffchen-9ta.com",
|
|
hostname: "www.xn--ffchen-9ta.com",
|
|
pathname: ";A/b/c",
|
|
search: "?d=e",
|
|
query: "d=e",
|
|
hash: "#f%20g%3Ch%3Ei",
|
|
path: ";A/b/c?d=e",
|
|
},
|
|
|
|
"http://SÉLIER.COM/": {
|
|
href: "http://xn--slier-bsa.com/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "xn--slier-bsa.com",
|
|
hostname: "xn--slier-bsa.com",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://ليهمابتكلموشعربي؟.ي؟/": {
|
|
href: "http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f",
|
|
hostname: "xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://➡.ws/➡": {
|
|
href: "http://xn--hgi.ws/➡",
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "xn--hgi.ws",
|
|
hostname: "xn--hgi.ws",
|
|
pathname: "/➡",
|
|
path: "/➡",
|
|
},
|
|
|
|
"http://bucket_name.s3.amazonaws.com/image.jpg": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "bucket_name.s3.amazonaws.com",
|
|
hostname: "bucket_name.s3.amazonaws.com",
|
|
pathname: "/image.jpg",
|
|
href: "http://bucket_name.s3.amazonaws.com/image.jpg",
|
|
path: "/image.jpg",
|
|
},
|
|
|
|
"git+http://github.com/joyent/node.git": {
|
|
protocol: "git+http:",
|
|
slashes: true,
|
|
host: "github.com",
|
|
hostname: "github.com",
|
|
pathname: "/joyent/node.git",
|
|
path: "/joyent/node.git",
|
|
href: "git+http://github.com/joyent/node.git",
|
|
},
|
|
|
|
// If local1@domain1 is uses as a relative URL it may
|
|
// be parse into auth@hostname, but here there is no
|
|
// way to make it work in URL.parse, I add the test to be explicit
|
|
"local1@domain1": {
|
|
pathname: "local1@domain1",
|
|
path: "local1@domain1",
|
|
href: "local1@domain1",
|
|
},
|
|
|
|
// While this may seem counter-intuitive, a browser will parse
|
|
// <a href='www.google.com'> as a path.
|
|
"www.example.com": {
|
|
href: "www.example.com",
|
|
pathname: "www.example.com",
|
|
path: "www.example.com",
|
|
},
|
|
|
|
// ipv6 support
|
|
"[fe80::1]": {
|
|
href: "[fe80::1]",
|
|
pathname: "[fe80::1]",
|
|
path: "[fe80::1]",
|
|
},
|
|
|
|
"coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]": {
|
|
protocol: "coap:",
|
|
slashes: true,
|
|
host: "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]",
|
|
hostname: "fedc:ba98:7654:3210:fedc:ba98:7654:3210",
|
|
href: "coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
// TODO: Support parsing this.
|
|
//
|
|
// "coap://[1080:0:0:0:8:800:200C:417A]:61616/": {
|
|
// protocol: "coap:",
|
|
// slashes: true,
|
|
// host: "[1080:0:0:0:8:800:200c:417a]:61616",
|
|
// port: "61616",
|
|
// hostname: "1080:0:0:0:8:800:200c:417a",
|
|
// href: "coap://[1080:0:0:0:8:800:200c:417a]:61616/",
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// },
|
|
|
|
"http://user:password@[3ffe:2a00:100:7031::1]:8080": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:password",
|
|
host: "[3ffe:2a00:100:7031::1]:8080",
|
|
port: "8080",
|
|
hostname: "3ffe:2a00:100:7031::1",
|
|
href: "http://user:password@[3ffe:2a00:100:7031::1]:8080/",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
// TODO: Support parsing this.
|
|
//
|
|
// "coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature": {
|
|
// protocol: "coap:",
|
|
// slashes: true,
|
|
// auth: "u:p",
|
|
// host: "[::192.9.5.5]:61616",
|
|
// port: "61616",
|
|
// hostname: "::192.9.5.5",
|
|
// href: "coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature",
|
|
// search: "?n=Temperature",
|
|
// query: "n=Temperature",
|
|
// pathname: "/.well-known/r",
|
|
// path: "/.well-known/r?n=Temperature",
|
|
// },
|
|
|
|
// empty port
|
|
"http://example.com:": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.com",
|
|
hostname: "example.com",
|
|
href: "http://example.com/",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://example.com:/a/b.html": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.com",
|
|
hostname: "example.com",
|
|
href: "http://example.com/a/b.html",
|
|
pathname: "/a/b.html",
|
|
path: "/a/b.html",
|
|
},
|
|
|
|
"http://example.com:?a=b": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.com",
|
|
hostname: "example.com",
|
|
href: "http://example.com/?a=b",
|
|
search: "?a=b",
|
|
query: "a=b",
|
|
pathname: "/",
|
|
path: "/?a=b",
|
|
},
|
|
|
|
"http://example.com:#abc": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "example.com",
|
|
hostname: "example.com",
|
|
href: "http://example.com/#abc",
|
|
hash: "#abc",
|
|
pathname: "/",
|
|
path: "/",
|
|
},
|
|
|
|
"http://[fe80::1]:/a/b?a=b#abc": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "[fe80::1]",
|
|
hostname: "fe80::1",
|
|
href: "http://[fe80::1]/a/b?a=b#abc",
|
|
search: "?a=b",
|
|
query: "a=b",
|
|
hash: "#abc",
|
|
pathname: "/a/b",
|
|
path: "/a/b?a=b",
|
|
},
|
|
|
|
"http://-lovemonsterz.tumblr.com/rss": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "-lovemonsterz.tumblr.com",
|
|
hostname: "-lovemonsterz.tumblr.com",
|
|
href: "http://-lovemonsterz.tumblr.com/rss",
|
|
pathname: "/rss",
|
|
path: "/rss",
|
|
},
|
|
|
|
"http://-lovemonsterz.tumblr.com:80/rss": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
port: "80",
|
|
host: "-lovemonsterz.tumblr.com:80",
|
|
hostname: "-lovemonsterz.tumblr.com",
|
|
href: "http://-lovemonsterz.tumblr.com:80/rss",
|
|
pathname: "/rss",
|
|
path: "/rss",
|
|
},
|
|
|
|
"http://user:pass@-lovemonsterz.tumblr.com/rss": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pass",
|
|
host: "-lovemonsterz.tumblr.com",
|
|
hostname: "-lovemonsterz.tumblr.com",
|
|
href: "http://user:pass@-lovemonsterz.tumblr.com/rss",
|
|
pathname: "/rss",
|
|
path: "/rss",
|
|
},
|
|
|
|
"http://user:pass@-lovemonsterz.tumblr.com:80/rss": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pass",
|
|
port: "80",
|
|
host: "-lovemonsterz.tumblr.com:80",
|
|
hostname: "-lovemonsterz.tumblr.com",
|
|
href: "http://user:pass@-lovemonsterz.tumblr.com:80/rss",
|
|
pathname: "/rss",
|
|
path: "/rss",
|
|
},
|
|
|
|
"http://_jabber._tcp.google.com/test": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "_jabber._tcp.google.com",
|
|
hostname: "_jabber._tcp.google.com",
|
|
href: "http://_jabber._tcp.google.com/test",
|
|
pathname: "/test",
|
|
path: "/test",
|
|
},
|
|
|
|
"http://user:pass@_jabber._tcp.google.com/test": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pass",
|
|
host: "_jabber._tcp.google.com",
|
|
hostname: "_jabber._tcp.google.com",
|
|
href: "http://user:pass@_jabber._tcp.google.com/test",
|
|
pathname: "/test",
|
|
path: "/test",
|
|
},
|
|
|
|
"http://_jabber._tcp.google.com:80/test": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
port: "80",
|
|
host: "_jabber._tcp.google.com:80",
|
|
hostname: "_jabber._tcp.google.com",
|
|
href: "http://_jabber._tcp.google.com:80/test",
|
|
pathname: "/test",
|
|
path: "/test",
|
|
},
|
|
|
|
"http://user:pass@_jabber._tcp.google.com:80/test": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "user:pass",
|
|
port: "80",
|
|
host: "_jabber._tcp.google.com:80",
|
|
hostname: "_jabber._tcp.google.com",
|
|
href: "http://user:pass@_jabber._tcp.google.com:80/test",
|
|
pathname: "/test",
|
|
path: "/test",
|
|
},
|
|
|
|
"http://x:1/' <>\"`/{}|\\^~`/": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
host: "x:1",
|
|
port: "1",
|
|
hostname: "x",
|
|
pathname: "/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/",
|
|
path: "/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/",
|
|
href: "http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/",
|
|
},
|
|
|
|
"http://a@b@c/": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "a@b",
|
|
host: "c",
|
|
hostname: "c",
|
|
href: "http://a%40b@c/",
|
|
path: "/",
|
|
pathname: "/",
|
|
},
|
|
|
|
"http://a@b?@c": {
|
|
protocol: "http:",
|
|
slashes: true,
|
|
auth: "a",
|
|
host: "b",
|
|
hostname: "b",
|
|
href: "http://a@b/?@c",
|
|
path: "/?@c",
|
|
pathname: "/",
|
|
search: "?@c",
|
|
query: "@c",
|
|
},
|
|
// TODO: Support parsing these.
|
|
//
|
|
// "http://a.b/\tbc\ndr\ref g\"hq'j<kl>?mn\\op^q=r`99{st|uv}wz": {
|
|
// protocol: "http:",
|
|
// slashes: true,
|
|
// host: "a.b",
|
|
// port: null,
|
|
// hostname: "a.b",
|
|
// hash: null,
|
|
// pathname: "/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E",
|
|
// path: "/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz",
|
|
// search: "?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz",
|
|
// query: "mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz",
|
|
// href: "http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz",
|
|
// },
|
|
|
|
// "http://a\r\" \t\n<'b:b@c\r\nd/e?f": {
|
|
// protocol: "http:",
|
|
// slashes: true,
|
|
// auth: "a\" <'b:b",
|
|
// host: "cd",
|
|
// port: null,
|
|
// hostname: "cd",
|
|
// hash: null,
|
|
// search: "?f",
|
|
// query: "f",
|
|
// pathname: "/e",
|
|
// path: "/e?f",
|
|
// href: "http://a%22%20%3C'b:b@cd/e?f",
|
|
// },
|
|
|
|
// Git urls used by npm
|
|
"git+ssh://git@github.com:npm/npm": {
|
|
protocol: "git+ssh:",
|
|
slashes: true,
|
|
auth: "git",
|
|
host: "github.com",
|
|
port: null,
|
|
hostname: "github.com",
|
|
hash: null,
|
|
search: null,
|
|
query: null,
|
|
pathname: "/:npm/npm",
|
|
path: "/:npm/npm",
|
|
href: "git+ssh://git@github.com/:npm/npm",
|
|
},
|
|
// TODO: Support parsing these.
|
|
//
|
|
// "https://*": {
|
|
// protocol: "https:",
|
|
// slashes: true,
|
|
// auth: null,
|
|
// host: "*",
|
|
// port: null,
|
|
// hostname: "*",
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "https://*/",
|
|
// },
|
|
|
|
// The following two URLs are the same, but they differ for a capital A.
|
|
// Verify that the protocol is checked in a case-insensitive manner.
|
|
// "javascript:alert(1);a=\x27@white-listed.com\x27": {
|
|
// protocol: "javascript:",
|
|
// slashes: null,
|
|
// auth: null,
|
|
// host: null,
|
|
// port: null,
|
|
// hostname: null,
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "alert(1);a='@white-listed.com'",
|
|
// path: "alert(1);a='@white-listed.com'",
|
|
// href: "javascript:alert(1);a='@white-listed.com'",
|
|
// },
|
|
|
|
// "javAscript:alert(1);a=\x27@white-listed.com\x27": {
|
|
// protocol: "javascript:",
|
|
// slashes: null,
|
|
// auth: null,
|
|
// host: null,
|
|
// port: null,
|
|
// hostname: null,
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "alert(1);a='@white-listed.com'",
|
|
// path: "alert(1);a='@white-listed.com'",
|
|
// href: "javascript:alert(1);a='@white-listed.com'",
|
|
// },
|
|
|
|
// "ws://www.example.com": {
|
|
// protocol: "ws:",
|
|
// slashes: true,
|
|
// hostname: "www.example.com",
|
|
// host: "www.example.com",
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "ws://www.example.com/",
|
|
// },
|
|
|
|
// "wss://www.example.com": {
|
|
// protocol: "wss:",
|
|
// slashes: true,
|
|
// hostname: "www.example.com",
|
|
// host: "www.example.com",
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "wss://www.example.com/",
|
|
// },
|
|
|
|
// "//fhqwhgads@example.com/everybody-to-the-limit": {
|
|
// protocol: null,
|
|
// slashes: true,
|
|
// auth: "fhqwhgads",
|
|
// host: "example.com",
|
|
// port: null,
|
|
// hostname: "example.com",
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "/everybody-to-the-limit",
|
|
// path: "/everybody-to-the-limit",
|
|
// href: "//fhqwhgads@example.com/everybody-to-the-limit",
|
|
// },
|
|
|
|
"//fhqwhgads@example.com/everybody#to-the-limit": {
|
|
protocol: null,
|
|
slashes: true,
|
|
auth: "fhqwhgads",
|
|
host: "example.com",
|
|
port: null,
|
|
hostname: "example.com",
|
|
hash: "#to-the-limit",
|
|
search: null,
|
|
query: null,
|
|
pathname: "/everybody",
|
|
path: "/everybody",
|
|
href: "//fhqwhgads@example.com/everybody#to-the-limit",
|
|
},
|
|
// TODO: Support parsing these.
|
|
//
|
|
// "\bhttp://example.com/\b": {
|
|
// protocol: "http:",
|
|
// slashes: true,
|
|
// auth: null,
|
|
// host: "example.com",
|
|
// port: null,
|
|
// hostname: "example.com",
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "http://example.com/",
|
|
// },
|
|
|
|
// "https://evil.com$.example.com": {
|
|
// protocol: "https:",
|
|
// slashes: true,
|
|
// auth: null,
|
|
// host: "evil.com$.example.com",
|
|
// port: null,
|
|
// hostname: "evil.com$.example.com",
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "https://evil.com$.example.com/",
|
|
// },
|
|
|
|
// Validate the output of hostname with commas.
|
|
// "x://0.0,1.1/": {
|
|
// protocol: "x:",
|
|
// slashes: true,
|
|
// auth: null,
|
|
// host: "0.0,1.1",
|
|
// port: null,
|
|
// hostname: "0.0,1.1",
|
|
// hash: null,
|
|
// search: null,
|
|
// query: null,
|
|
// pathname: "/",
|
|
// path: "/",
|
|
// href: "x://0.0,1.1/",
|
|
// },
|
|
};
|
|
|
|
test("url.parse", () => {
|
|
for (const u in parseTests) {
|
|
let actual = url.parse(u);
|
|
const spaced = url.parse(` \t ${u}\n\t`);
|
|
let expected = Object.assign(new url.Url(), parseTests[u]);
|
|
|
|
Object.keys(actual).forEach(function (i) {
|
|
if (expected[i] === undefined && actual[i] === null) {
|
|
expected[i] = null;
|
|
}
|
|
});
|
|
|
|
assert.deepStrictEqual(
|
|
actual,
|
|
expected,
|
|
`parsing ${u} and expected ${inspect(expected)} but got ${inspect(actual)}`,
|
|
);
|
|
assert.deepStrictEqual(spaced, expected, `expected ${inspect(expected)}, got ${inspect(spaced)}`);
|
|
}
|
|
});
|
|
|
|
test("url.format", () => {
|
|
for (const u in parseTests) {
|
|
const expected = parseTests[u].href;
|
|
const actual = url.format(parseTests[u]);
|
|
|
|
assert.strictEqual(actual, expected, `format(${u}) == ${u}\nactual:${actual}`);
|
|
}
|
|
});
|
|
|
|
// TODO: Support parsing this.
|
|
test.todo("xss", () => {
|
|
const parsed = url.parse("http://nodejs.org/").resolveObject("jAvascript:alert(1);a=\x27@white-listed.com\x27");
|
|
|
|
const expected = Object.assign(new url.Url(), {
|
|
protocol: "javascript:",
|
|
slashes: null,
|
|
auth: null,
|
|
host: null,
|
|
port: null,
|
|
hostname: null,
|
|
hash: null,
|
|
search: null,
|
|
query: null,
|
|
pathname: "alert(1);a='@white-listed.com'",
|
|
path: "alert(1);a='@white-listed.com'",
|
|
href: "javascript:alert(1);a='@white-listed.com'",
|
|
});
|
|
|
|
assert.deepStrictEqual(parsed, expected);
|
|
});
|
|
});
|