| # Copyright Joyent, Inc. and other Node contributors. |
| # |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the |
| # "Software"), to deal in the Software without restriction, including |
| # without limitation the rights to use, copy, modify, merge, publish, |
| # distribute, sublicense, and/or sell copies of the Software, and to permit |
| # persons to whom the Software is furnished to do so, subject to the |
| # following conditions: |
| # |
| # The above copyright notice and this permission notice shall be included |
| # in all copies or substantial portions of the Software. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| # USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| |
| # URLs to parse, and expected data |
| # { url : parsed } |
| PARSED = { |
| "//some_path": {"pathname": "//some_path"}, |
| "HTTP://www.example.com/": { |
| "protocol": "HTTP:", |
| "slashes": True, |
| "hostname": "www.example.com", |
| "pathname": "/", |
| }, |
| "HTTP://www.example.com": { |
| "protocol": "HTTP:", |
| "slashes": True, |
| "hostname": "www.example.com", |
| "pathname": "", |
| }, |
| "http://www.ExAmPlE.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "www.ExAmPlE.com", |
| "pathname": "/", |
| }, |
| "http://user:pw@www.ExAmPlE.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pw", |
| "hostname": "www.ExAmPlE.com", |
| "pathname": "/", |
| }, |
| "http://USER:PW@www.ExAmPlE.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "USER:PW", |
| "hostname": "www.ExAmPlE.com", |
| "pathname": "/", |
| }, |
| "http://user@www.example.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user", |
| "hostname": "www.example.com", |
| "pathname": "/", |
| }, |
| "http://user%3Apw@www.example.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user%3Apw", |
| "hostname": "www.example.com", |
| "pathname": "/", |
| }, |
| "http://x.com/path?that's#all, folks": { |
| "protocol": "http:", |
| "hostname": "x.com", |
| "slashes": True, |
| "search": "?that's", |
| "pathname": "/path", |
| "hash": "#all, folks", |
| }, |
| "HTTP://X.COM/Y": { |
| "protocol": "HTTP:", |
| "slashes": True, |
| "hostname": "X.COM", |
| "pathname": "/Y", |
| }, |
| # + not an invalid host character |
| # per https://url.spec.whatwg.org/#host-parsing |
| "http://x.y.com+a/b/c": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "x.y.com+a", |
| "pathname": "/b/c", |
| }, |
| # an unexpected invalid char in the hostname. |
| "HtTp://x.y.cOm;a/b/c?d=e#f g<h>i": { |
| "protocol": "HtTp:", |
| "slashes": True, |
| "hostname": "x.y.cOm", |
| "pathname": ";a/b/c", |
| "search": "?d=e", |
| "hash": "#f g<h>i", |
| }, |
| # make sure that we don't accidentally lcast the path parts. |
| "HtTp://x.y.cOm;A/b/c?d=e#f g<h>i": { |
| "protocol": "HtTp:", |
| "slashes": True, |
| "hostname": "x.y.cOm", |
| "pathname": ";A/b/c", |
| "search": "?d=e", |
| "hash": "#f g<h>i", |
| }, |
| "http://x...y...#p": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "x...y...", |
| "hash": "#p", |
| "pathname": "", |
| }, |
| 'http://x/p/"quoted"': { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "x", |
| "pathname": '/p/"quoted"', |
| }, |
| "<http://goo.corn/bread> Is a URL!": { |
| "pathname": "<http://goo.corn/bread> Is a URL!" |
| }, |
| "http://www.narwhaljs.org/blog/categories?id=news": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "www.narwhaljs.org", |
| "search": "?id=news", |
| "pathname": "/blog/categories", |
| }, |
| "http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "mt0.google.com", |
| "pathname": "/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=": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "mt0.google.com", |
| "search": "???&hl=en&src=api&x=2&y=2&z=3&s=", |
| "pathname": "/vt/lyrs=m@114", |
| }, |
| "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, |
| "auth": "user:pass", |
| "hostname": "mt0.google.com", |
| "search": "???&hl=en&src=api&x=2&y=2&z=3&s=", |
| "pathname": "/vt/lyrs=m@114", |
| }, |
| "file:///etc/passwd": { |
| "slashes": True, |
| "protocol": "file:", |
| "pathname": "/etc/passwd", |
| "hostname": "", |
| }, |
| "file://localhost/etc/passwd": { |
| "protocol": "file:", |
| "slashes": True, |
| "pathname": "/etc/passwd", |
| "hostname": "localhost", |
| }, |
| "file://foo/etc/passwd": { |
| "protocol": "file:", |
| "slashes": True, |
| "pathname": "/etc/passwd", |
| "hostname": "foo", |
| }, |
| "file:///etc/node/": { |
| "slashes": True, |
| "protocol": "file:", |
| "pathname": "/etc/node/", |
| "hostname": "", |
| }, |
| "file://localhost/etc/node/": { |
| "protocol": "file:", |
| "slashes": True, |
| "pathname": "/etc/node/", |
| "hostname": "localhost", |
| }, |
| "file://foo/etc/node/": { |
| "protocol": "file:", |
| "slashes": True, |
| "pathname": "/etc/node/", |
| "hostname": "foo", |
| }, |
| "http:/baz/../foo/bar": {"protocol": "http:", "pathname": "/baz/../foo/bar"}, |
| "http://user:pass@example.com:8000/foo/bar?baz=quux#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pass", |
| "port": "8000", |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?baz=quux", |
| "pathname": "/foo/bar", |
| }, |
| "//user:pass@example.com:8000/foo/bar?baz=quux#frag": { |
| "slashes": True, |
| "auth": "user:pass", |
| "port": "8000", |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?baz=quux", |
| "pathname": "/foo/bar", |
| }, |
| "/foo/bar?baz=quux#frag": { |
| "hash": "#frag", |
| "search": "?baz=quux", |
| "pathname": "/foo/bar", |
| }, |
| "http:/foo/bar?baz=quux#frag": { |
| "protocol": "http:", |
| "hash": "#frag", |
| "search": "?baz=quux", |
| "pathname": "/foo/bar", |
| }, |
| "mailto:foo@bar.com?subject=hello": { |
| "protocol": "mailto:", |
| "auth": "foo", |
| "hostname": "bar.com", |
| "search": "?subject=hello", |
| }, |
| "javascript:alert('hello');": { |
| "protocol": "javascript:", |
| "pathname": "alert('hello');", |
| }, |
| "xmpp:isaacschlueter@jabber.org": { |
| "protocol": "xmpp:", |
| "auth": "isaacschlueter", |
| "hostname": "jabber.org", |
| }, |
| "http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "atpass:foo%40bar", |
| "hostname": "127.0.0.1", |
| "port": "8080", |
| "pathname": "/path", |
| "search": "?search=foo", |
| "hash": "#bar", |
| }, |
| "svn+ssh://foo/bar": { |
| "hostname": "foo", |
| "protocol": "svn+ssh:", |
| "pathname": "/bar", |
| "slashes": True, |
| }, |
| "dash-test://foo/bar": { |
| "hostname": "foo", |
| "protocol": "dash-test:", |
| "pathname": "/bar", |
| "slashes": True, |
| }, |
| "dash-test:foo/bar": { |
| "hostname": "foo", |
| "protocol": "dash-test:", |
| "pathname": "/bar", |
| }, |
| "dot.test://foo/bar": { |
| "hostname": "foo", |
| "protocol": "dot.test:", |
| "pathname": "/bar", |
| "slashes": True, |
| }, |
| "dot.test:foo/bar": { |
| "hostname": "foo", |
| "protocol": "dot.test:", |
| "pathname": "/bar", |
| }, |
| # IDNA tests |
| "http://www.日本語.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "www.日本語.com", |
| "pathname": "/", |
| }, |
| "http://example.Bücher.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.Bücher.com", |
| "pathname": "/", |
| }, |
| "http://www.Äffchen.com/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "www.Äffchen.com", |
| "pathname": "/", |
| }, |
| "http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "www.Äffchen.cOm", |
| "pathname": ";A/b/c", |
| "search": "?d=e", |
| "hash": "#f g<h>i", |
| }, |
| "http://SÉLIER.COM/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "SÉLIER.COM", |
| "pathname": "/", |
| }, |
| "http://ليهمابتكلموشعربي؟.ي؟/": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "ليهمابتكلموشعربي؟.ي؟", |
| "pathname": "/", |
| }, |
| "http://âž¡.ws/âž¡": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "âž¡.ws", |
| "pathname": "/âž¡", |
| }, |
| "http://bucket_name.s3.amazonaws.com/image.jpg": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "bucket_name.s3.amazonaws.com", |
| "pathname": "/image.jpg", |
| }, |
| "git+http://github.com/joyent/node.git": { |
| "protocol": "git+http:", |
| "slashes": True, |
| "hostname": "github.com", |
| "pathname": "/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"}, |
| # While this may seem counter-intuitive, a browser will parse |
| # <a href='www.google.com'> as a path. |
| "www.example.com": {"pathname": "www.example.com"}, |
| # ipv6 support |
| "[fe80::1]": {"pathname": "[fe80::1]"}, |
| "coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]": { |
| "protocol": "coap:", |
| "slashes": True, |
| "hostname": "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", |
| }, |
| "coap://[1080:0:0:0:8:800:200C:417A]:61616/": { |
| "protocol": "coap:", |
| "slashes": True, |
| "port": "61616", |
| "hostname": "1080:0:0:0:8:800:200C:417A", |
| "pathname": "/", |
| }, |
| "http://user:password@[3ffe:2a00:100:7031::1]:8080": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:password", |
| "port": "8080", |
| "hostname": "3ffe:2a00:100:7031::1", |
| "pathname": "", |
| }, |
| "coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature": { |
| "protocol": "coap:", |
| "slashes": True, |
| "auth": "u:p", |
| "port": "61616", |
| "hostname": "::192.9.5.5", |
| "search": "?n=Temperature", |
| "pathname": "/.well-known/r", |
| }, |
| # empty port |
| "http://example.com:": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "pathname": ":", |
| }, |
| "http://example.com:/a/b.html": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "pathname": ":/a/b.html", |
| }, |
| "http://example.com:?a=b": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "search": "?a=b", |
| "pathname": ":", |
| }, |
| "http://example.com:#abc": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#abc", |
| "pathname": ":", |
| }, |
| "http://[fe80::1]:/a/b?a=b#abc": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "fe80::1", |
| "search": "?a=b", |
| "hash": "#abc", |
| "pathname": ":/a/b", |
| }, |
| "http://-lovemonsterz.tumblr.com/rss": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "-lovemonsterz.tumblr.com", |
| "pathname": "/rss", |
| }, |
| "http://-lovemonsterz.tumblr.com:80/rss": { |
| "protocol": "http:", |
| "slashes": True, |
| "port": "80", |
| "hostname": "-lovemonsterz.tumblr.com", |
| "pathname": "/rss", |
| }, |
| "http://user:pass@-lovemonsterz.tumblr.com/rss": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pass", |
| "hostname": "-lovemonsterz.tumblr.com", |
| "pathname": "/rss", |
| }, |
| "http://user:pass@-lovemonsterz.tumblr.com:80/rss": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pass", |
| "port": "80", |
| "hostname": "-lovemonsterz.tumblr.com", |
| "pathname": "/rss", |
| }, |
| "http://_jabber._tcp.google.com/test": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "_jabber._tcp.google.com", |
| "pathname": "/test", |
| }, |
| "http://user:pass@_jabber._tcp.google.com/test": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pass", |
| "hostname": "_jabber._tcp.google.com", |
| "pathname": "/test", |
| }, |
| "http://_jabber._tcp.google.com:80/test": { |
| "protocol": "http:", |
| "slashes": True, |
| "port": "80", |
| "hostname": "_jabber._tcp.google.com", |
| "pathname": "/test", |
| }, |
| "http://user:pass@_jabber._tcp.google.com:80/test": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "user:pass", |
| "port": "80", |
| "hostname": "_jabber._tcp.google.com", |
| "pathname": "/test", |
| }, |
| "http://x:1/' <>\"`/{}|\\^~`/": { |
| "protocol": "http:", |
| "slashes": True, |
| "port": "1", |
| "hostname": "x", |
| "pathname": "/' <>\"`/{}|\\^~`/", |
| }, |
| "http://a@b@c/": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "a@b", |
| "hostname": "c", |
| "pathname": "/", |
| }, |
| "http://a@b?@c": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "a", |
| "hostname": "b", |
| "pathname": "", |
| "search": "?@c", |
| }, |
| "http://a\r\" \t\n<'b:b@c\r\nd/e?f": { |
| "protocol": "http:", |
| "slashes": True, |
| "auth": "a\r\" \t\n<'b:b", |
| "hostname": "c", |
| "search": "?f", |
| "pathname": "\r\nd/e", |
| }, |
| # git urls used by npm |
| "git+ssh://git@github.com:npm/npm": { |
| "protocol": "git+ssh:", |
| "slashes": True, |
| "auth": "git", |
| "hostname": "github.com", |
| "pathname": ":npm/npm", |
| }, |
| "http://example.com?foo=bar#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?foo=bar", |
| "pathname": "", |
| }, |
| "http://example.com?foo=@bar#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?foo=@bar", |
| "pathname": "", |
| }, |
| "http://example.com?foo=/bar/#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?foo=/bar/", |
| "pathname": "", |
| }, |
| "http://example.com?foo=?bar/#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#frag", |
| "search": "?foo=?bar/", |
| "pathname": "", |
| }, |
| "http://example.com#frag=?bar/#frag": { |
| "protocol": "http:", |
| "slashes": True, |
| "hostname": "example.com", |
| "hash": "#frag=?bar/#frag", |
| "pathname": "", |
| }, |
| 'http://google.com" onload="alert(42)/': { |
| "hostname": "google.com", |
| "protocol": "http:", |
| "slashes": True, |
| "pathname": '" onload="alert(42)/', |
| }, |
| "http://a.com/a/b/c?s#h": { |
| "protocol": "http:", |
| "slashes": True, |
| "pathname": "/a/b/c", |
| "hostname": "a.com", |
| "hash": "#h", |
| "search": "?s", |
| }, |
| "http://atpass:foo%40bar@127.0.0.1/": { |
| "auth": "atpass:foo%40bar", |
| "slashes": True, |
| "hostname": "127.0.0.1", |
| "protocol": "http:", |
| "pathname": "/", |
| }, |
| "http://atslash%2F%40:%2F%40@foo/": { |
| "auth": "atslash%2F%40:%2F%40", |
| "hostname": "foo", |
| "protocol": "http:", |
| "pathname": "/", |
| "slashes": True, |
| }, |
| # ipv6 support |
| "coap:u:p@[::1]:61616/.well-known/r?n=Temperature": { |
| "protocol": "coap:", |
| "auth": "u:p", |
| "hostname": "::1", |
| "port": "61616", |
| "pathname": "/.well-known/r", |
| "search": "?n=Temperature", |
| }, |
| "coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton": { |
| "hostname": "fedc:ba98:7654:3210:fedc:ba98:7654:3210", |
| "port": "61616", |
| "protocol": "coap:", |
| "pathname": "/s/stopButton", |
| }, |
| # encode context-specific delimiters in path and query, but do not touch |
| # other non-delimiter chars like `%`. |
| # <https://github.com/joyent/node/issues/4082> |
| # `?` and `#` in path and search |
| "http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag": { |
| "protocol": "http:", |
| "hostname": "ex.com", |
| "hash": "#frag", |
| "search": "?abc=the%231?&foo=bar", |
| "pathname": "/foo%3F100%m%23r", |
| "slashes": True, |
| }, |
| # `?` and `#` in search only |
| "http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag": { |
| "protocol": "http:", |
| "hostname": "ex.com", |
| "hash": "#frag", |
| "search": "?abc=the%231?&foo=bar", |
| "pathname": "/fooA100%mBr", |
| "slashes": True, |
| }, |
| # |
| "http://": { |
| "protocol": "http:", |
| "hostname": "", |
| "slashes": True, |
| }, |
| } |