269 lines
7.0 KiB
JavaScript
269 lines
7.0 KiB
JavaScript
'use strict';
|
|
require('../common');
|
|
const assert = require('assert');
|
|
const url = require('url');
|
|
|
|
// Formatting tests to verify that it'll format slightly wonky content to a
|
|
// valid URL.
|
|
const formatTests = {
|
|
'http://example.com?': {
|
|
href: 'http://example.com/?',
|
|
protocol: 'http:',
|
|
slashes: true,
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
search: '?',
|
|
query: {},
|
|
pathname: '/'
|
|
},
|
|
'http://example.com?foo=bar#frag': {
|
|
href: 'http://example.com/?foo=bar#frag',
|
|
protocol: 'http:',
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag',
|
|
search: '?foo=bar',
|
|
query: 'foo=bar',
|
|
pathname: '/'
|
|
},
|
|
'http://example.com?foo=@bar#frag': {
|
|
href: 'http://example.com/?foo=@bar#frag',
|
|
protocol: 'http:',
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag',
|
|
search: '?foo=@bar',
|
|
query: 'foo=@bar',
|
|
pathname: '/'
|
|
},
|
|
'http://example.com?foo=/bar/#frag': {
|
|
href: 'http://example.com/?foo=/bar/#frag',
|
|
protocol: 'http:',
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag',
|
|
search: '?foo=/bar/',
|
|
query: 'foo=/bar/',
|
|
pathname: '/'
|
|
},
|
|
'http://example.com?foo=?bar/#frag': {
|
|
href: 'http://example.com/?foo=?bar/#frag',
|
|
protocol: 'http:',
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag',
|
|
search: '?foo=?bar/',
|
|
query: 'foo=?bar/',
|
|
pathname: '/'
|
|
},
|
|
'http://example.com#frag=?bar/#frag': {
|
|
href: 'http://example.com/#frag=?bar/#frag',
|
|
protocol: 'http:',
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag=?bar/#frag',
|
|
pathname: '/'
|
|
},
|
|
'http://google.com" onload="alert(42)/': {
|
|
href: 'http://google.com/%22%20onload=%22alert(42)/',
|
|
protocol: 'http:',
|
|
host: 'google.com',
|
|
pathname: '/%22%20onload=%22alert(42)/'
|
|
},
|
|
'http://a.com/a/b/c?s#h': {
|
|
href: 'http://a.com/a/b/c?s#h',
|
|
protocol: 'http',
|
|
host: 'a.com',
|
|
pathname: 'a/b/c',
|
|
hash: 'h',
|
|
search: 's'
|
|
},
|
|
'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/': {
|
|
href: 'http://atpass:foo%40bar@127.0.0.1/',
|
|
auth: 'atpass:foo@bar',
|
|
hostname: '127.0.0.1',
|
|
protocol: 'http:',
|
|
pathname: '/'
|
|
},
|
|
'http://atslash%2F%40:%2F%40@foo/': {
|
|
href: 'http://atslash%2F%40:%2F%40@foo/',
|
|
auth: 'atslash/@:/@',
|
|
hostname: 'foo',
|
|
protocol: 'http:',
|
|
pathname: '/'
|
|
},
|
|
'svn+ssh://foo/bar': {
|
|
href: 'svn+ssh://foo/bar',
|
|
hostname: 'foo',
|
|
protocol: 'svn+ssh:',
|
|
pathname: '/bar',
|
|
slashes: true
|
|
},
|
|
'dash-test://foo/bar': {
|
|
href: 'dash-test://foo/bar',
|
|
hostname: 'foo',
|
|
protocol: 'dash-test:',
|
|
pathname: '/bar',
|
|
slashes: true
|
|
},
|
|
'dash-test:foo/bar': {
|
|
href: 'dash-test:foo/bar',
|
|
hostname: 'foo',
|
|
protocol: 'dash-test:',
|
|
pathname: '/bar'
|
|
},
|
|
'dot.test://foo/bar': {
|
|
href: 'dot.test://foo/bar',
|
|
hostname: 'foo',
|
|
protocol: 'dot.test:',
|
|
pathname: '/bar',
|
|
slashes: true
|
|
},
|
|
'dot.test:foo/bar': {
|
|
href: 'dot.test:foo/bar',
|
|
hostname: 'foo',
|
|
protocol: 'dot.test:',
|
|
pathname: '/bar'
|
|
},
|
|
// IPv6 support
|
|
'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
|
|
href: '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': {
|
|
href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
|
|
protocol: 'coap',
|
|
host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
|
|
pathname: '/s/stopButton'
|
|
},
|
|
|
|
// Encode context-specific delimiters in path and query, but do not touch
|
|
// other non-delimiter chars like `%`.
|
|
// <https://github.com/nodejs/node-v0.x-archive/issues/4082>
|
|
|
|
// `#`,`?` in path
|
|
'/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
|
|
href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
|
|
pathname: '/path/to/%#?+=&.txt',
|
|
query: {
|
|
foo: 'theA1'
|
|
},
|
|
hash: '#bar'
|
|
},
|
|
|
|
// `#`,`?` in path + `#` in query
|
|
'/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
|
|
href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
|
|
pathname: '/path/to/%#?+=&.txt',
|
|
query: {
|
|
foo: 'the#1'
|
|
},
|
|
hash: '#bar'
|
|
},
|
|
|
|
// `#` in path end + `#` in query
|
|
'/path/to/%%23?foo=the%231#bar': {
|
|
href: '/path/to/%%23?foo=the%231#bar',
|
|
pathname: '/path/to/%#',
|
|
query: {
|
|
foo: 'the#1'
|
|
},
|
|
hash: '#bar'
|
|
},
|
|
|
|
// `?` and `#` in path and search
|
|
'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
|
|
href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
|
|
protocol: 'http:',
|
|
hostname: 'ex.com',
|
|
hash: '#frag',
|
|
search: '?abc=the#1?&foo=bar',
|
|
pathname: '/foo?100%m#r',
|
|
},
|
|
|
|
// `?` and `#` in search only
|
|
'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
|
|
href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
|
|
protocol: 'http:',
|
|
hostname: 'ex.com',
|
|
hash: '#frag',
|
|
search: '?abc=the#1?&foo=bar',
|
|
pathname: '/fooA100%mBr',
|
|
},
|
|
|
|
// Multiple `#` in search
|
|
'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': {
|
|
href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag',
|
|
protocol: 'http:',
|
|
slashes: true,
|
|
host: 'example.com',
|
|
hostname: 'example.com',
|
|
hash: '#frag',
|
|
search: '?foo=bar#1#2#3&abc=#4##5',
|
|
query: {},
|
|
pathname: '/'
|
|
},
|
|
|
|
// More than 255 characters in hostname which exceeds the limit
|
|
[`http://${'a'.repeat(255)}.com/node`]: {
|
|
href: 'http:///node',
|
|
protocol: 'http:',
|
|
slashes: true,
|
|
host: '',
|
|
hostname: '',
|
|
pathname: '/node',
|
|
path: '/node'
|
|
},
|
|
|
|
// Greater than or equal to 63 characters after `.` in hostname
|
|
[`http://www.${'z'.repeat(63)}example.com/node`]: {
|
|
href: `http://www.${'z'.repeat(63)}example.com/node`,
|
|
protocol: 'http:',
|
|
slashes: true,
|
|
host: `www.${'z'.repeat(63)}example.com`,
|
|
hostname: `www.${'z'.repeat(63)}example.com`,
|
|
pathname: '/node',
|
|
path: '/node'
|
|
},
|
|
|
|
// https://github.com/nodejs/node/issues/3361
|
|
'file:///home/user': {
|
|
href: 'file:///home/user',
|
|
protocol: 'file',
|
|
pathname: '/home/user',
|
|
path: '/home/user'
|
|
},
|
|
|
|
// surrogate in auth
|
|
'http://%F0%9F%98%80@www.example.com/': {
|
|
href: 'http://%F0%9F%98%80@www.example.com/',
|
|
protocol: 'http:',
|
|
auth: '\uD83D\uDE00',
|
|
hostname: 'www.example.com',
|
|
pathname: '/'
|
|
}
|
|
};
|
|
for (const u in formatTests) {
|
|
const expect = formatTests[u].href;
|
|
delete formatTests[u].href;
|
|
const actual = url.format(u);
|
|
const actualObj = url.format(formatTests[u]);
|
|
assert.strictEqual(actual, expect,
|
|
`wonky format(${u}) == ${expect}\nactual:${actual}`);
|
|
assert.strictEqual(actualObj, expect,
|
|
`wonky format(${JSON.stringify(formatTests[u])}) == ${
|
|
expect}\nactual: ${actualObj}`);
|
|
}
|