• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2require('../common');
3const assert = require('assert');
4const url = require('url');
5
6// Formatting tests to verify that it'll format slightly wonky content to a
7// valid URL.
8const formatTests = {
9  'http://example.com?': {
10    href: 'http://example.com/?',
11    protocol: 'http:',
12    slashes: true,
13    host: 'example.com',
14    hostname: 'example.com',
15    search: '?',
16    query: {},
17    pathname: '/'
18  },
19  'http://example.com?foo=bar#frag': {
20    href: 'http://example.com/?foo=bar#frag',
21    protocol: 'http:',
22    host: 'example.com',
23    hostname: 'example.com',
24    hash: '#frag',
25    search: '?foo=bar',
26    query: 'foo=bar',
27    pathname: '/'
28  },
29  'http://example.com?foo=@bar#frag': {
30    href: 'http://example.com/?foo=@bar#frag',
31    protocol: 'http:',
32    host: 'example.com',
33    hostname: 'example.com',
34    hash: '#frag',
35    search: '?foo=@bar',
36    query: 'foo=@bar',
37    pathname: '/'
38  },
39  'http://example.com?foo=/bar/#frag': {
40    href: 'http://example.com/?foo=/bar/#frag',
41    protocol: 'http:',
42    host: 'example.com',
43    hostname: 'example.com',
44    hash: '#frag',
45    search: '?foo=/bar/',
46    query: 'foo=/bar/',
47    pathname: '/'
48  },
49  'http://example.com?foo=?bar/#frag': {
50    href: 'http://example.com/?foo=?bar/#frag',
51    protocol: 'http:',
52    host: 'example.com',
53    hostname: 'example.com',
54    hash: '#frag',
55    search: '?foo=?bar/',
56    query: 'foo=?bar/',
57    pathname: '/'
58  },
59  'http://example.com#frag=?bar/#frag': {
60    href: 'http://example.com/#frag=?bar/#frag',
61    protocol: 'http:',
62    host: 'example.com',
63    hostname: 'example.com',
64    hash: '#frag=?bar/#frag',
65    pathname: '/'
66  },
67  'http://google.com" onload="alert(42)/': {
68    href: 'http://google.com/%22%20onload=%22alert(42)/',
69    protocol: 'http:',
70    host: 'google.com',
71    pathname: '/%22%20onload=%22alert(42)/'
72  },
73  'http://a.com/a/b/c?s#h': {
74    href: 'http://a.com/a/b/c?s#h',
75    protocol: 'http',
76    host: 'a.com',
77    pathname: 'a/b/c',
78    hash: 'h',
79    search: 's'
80  },
81  'xmpp:isaacschlueter@jabber.org': {
82    href: 'xmpp:isaacschlueter@jabber.org',
83    protocol: 'xmpp:',
84    host: 'jabber.org',
85    auth: 'isaacschlueter',
86    hostname: 'jabber.org'
87  },
88  'http://atpass:foo%40bar@127.0.0.1/': {
89    href: 'http://atpass:foo%40bar@127.0.0.1/',
90    auth: 'atpass:foo@bar',
91    hostname: '127.0.0.1',
92    protocol: 'http:',
93    pathname: '/'
94  },
95  'http://atslash%2F%40:%2F%40@foo/': {
96    href: 'http://atslash%2F%40:%2F%40@foo/',
97    auth: 'atslash/@:/@',
98    hostname: 'foo',
99    protocol: 'http:',
100    pathname: '/'
101  },
102  'svn+ssh://foo/bar': {
103    href: 'svn+ssh://foo/bar',
104    hostname: 'foo',
105    protocol: 'svn+ssh:',
106    pathname: '/bar',
107    slashes: true
108  },
109  'dash-test://foo/bar': {
110    href: 'dash-test://foo/bar',
111    hostname: 'foo',
112    protocol: 'dash-test:',
113    pathname: '/bar',
114    slashes: true
115  },
116  'dash-test:foo/bar': {
117    href: 'dash-test:foo/bar',
118    hostname: 'foo',
119    protocol: 'dash-test:',
120    pathname: '/bar'
121  },
122  'dot.test://foo/bar': {
123    href: 'dot.test://foo/bar',
124    hostname: 'foo',
125    protocol: 'dot.test:',
126    pathname: '/bar',
127    slashes: true
128  },
129  'dot.test:foo/bar': {
130    href: 'dot.test:foo/bar',
131    hostname: 'foo',
132    protocol: 'dot.test:',
133    pathname: '/bar'
134  },
135  // IPv6 support
136  'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
137    href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
138    protocol: 'coap:',
139    auth: 'u:p',
140    hostname: '::1',
141    port: '61616',
142    pathname: '/.well-known/r',
143    search: 'n=Temperature'
144  },
145  'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
146    href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
147    protocol: 'coap',
148    host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
149    pathname: '/s/stopButton'
150  },
151  'http://[::]/': {
152    href: 'http://[::]/',
153    protocol: 'http:',
154    hostname: '[::]',
155    pathname: '/'
156  },
157
158  // Encode context-specific delimiters in path and query, but do not touch
159  // other non-delimiter chars like `%`.
160  // <https://github.com/nodejs/node-v0.x-archive/issues/4082>
161
162  // `#`,`?` in path
163  '/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
164    href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
165    pathname: '/path/to/%#?+=&.txt',
166    query: {
167      foo: 'theA1'
168    },
169    hash: '#bar'
170  },
171
172  // `#`,`?` in path + `#` in query
173  '/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
174    href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
175    pathname: '/path/to/%#?+=&.txt',
176    query: {
177      foo: 'the#1'
178    },
179    hash: '#bar'
180  },
181
182  // `#` in path end + `#` in query
183  '/path/to/%%23?foo=the%231#bar': {
184    href: '/path/to/%%23?foo=the%231#bar',
185    pathname: '/path/to/%#',
186    query: {
187      foo: 'the#1'
188    },
189    hash: '#bar'
190  },
191
192  // `?` and `#` in path and search
193  'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
194    href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
195    protocol: 'http:',
196    hostname: 'ex.com',
197    hash: '#frag',
198    search: '?abc=the#1?&foo=bar',
199    pathname: '/foo?100%m#r',
200  },
201
202  // `?` and `#` in search only
203  'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
204    href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
205    protocol: 'http:',
206    hostname: 'ex.com',
207    hash: '#frag',
208    search: '?abc=the#1?&foo=bar',
209    pathname: '/fooA100%mBr',
210  },
211
212  // Multiple `#` in search
213  'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': {
214    href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag',
215    protocol: 'http:',
216    slashes: true,
217    host: 'example.com',
218    hostname: 'example.com',
219    hash: '#frag',
220    search: '?foo=bar#1#2#3&abc=#4##5',
221    query: {},
222    pathname: '/'
223  },
224
225  // More than 255 characters in hostname which exceeds the limit
226  [`http://${'a'.repeat(255)}.com/node`]: {
227    href: 'http:///node',
228    protocol: 'http:',
229    slashes: true,
230    host: '',
231    hostname: '',
232    pathname: '/node',
233    path: '/node'
234  },
235
236  // Greater than or equal to 63 characters after `.` in hostname
237  [`http://www.${'z'.repeat(63)}example.com/node`]: {
238    href: `http://www.${'z'.repeat(63)}example.com/node`,
239    protocol: 'http:',
240    slashes: true,
241    host: `www.${'z'.repeat(63)}example.com`,
242    hostname: `www.${'z'.repeat(63)}example.com`,
243    pathname: '/node',
244    path: '/node'
245  },
246
247  // https://github.com/nodejs/node/issues/3361
248  'file:///home/user': {
249    href: 'file:///home/user',
250    protocol: 'file',
251    pathname: '/home/user',
252    path: '/home/user'
253  },
254
255  // surrogate in auth
256  'http://%F0%9F%98%80@www.example.com/': {
257    href: 'http://%F0%9F%98%80@www.example.com/',
258    protocol: 'http:',
259    auth: '\uD83D\uDE00',
260    hostname: 'www.example.com',
261    pathname: '/'
262  }
263};
264for (const u in formatTests) {
265  const expect = formatTests[u].href;
266  delete formatTests[u].href;
267  const actual = url.format(u);
268  const actualObj = url.format(formatTests[u]);
269  assert.strictEqual(actual, expect,
270                     `wonky format(${u}) == ${expect}\nactual:${actual}`);
271  assert.strictEqual(actualObj, expect,
272                     `wonky format(${JSON.stringify(formatTests[u])}) == ${
273                       expect}\nactual: ${actualObj}`);
274}
275