UNPKG

48.3 kBJavaScriptView Raw
1'use strict';
2
3/*
4 * Copyright Joyent, Inc. and other Node contributors.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to permit
11 * persons to whom the Software is furnished to do so, subject to the
12 * following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26var test = require('mocha').test;
27var assert = require('assert');
28var nodeURL = require('url');
29
30var url = require('../url');
31
32/*
33 * URLs to parse, and expected data
34 * { url : parsed }
35 */
36var parseTests = {
37 '//some_path': {
38 href: '//some_path',
39 pathname: '//some_path',
40 path: '//some_path'
41 },
42
43 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h': {
44 protocol: 'http:',
45 slashes: true,
46 host: 'evil-phisher',
47 hostname: 'evil-phisher',
48 pathname: '/foo.html',
49 path: '/foo.html',
50 hash: '#h%5Ca%5Cs%5Ch',
51 href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch'
52 },
53
54 'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': {
55 protocol: 'http:',
56 slashes: true,
57 host: 'evil-phisher',
58 hostname: 'evil-phisher',
59 pathname: '/foo.html',
60 search: '?json=%22%5C%22foo%5C%22%22',
61 query: 'json=%22%5C%22foo%5C%22%22',
62 path: '/foo.html?json=%22%5C%22foo%5C%22%22',
63 hash: '#h%5Ca%5Cs%5Ch',
64 href: 'http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch'
65 },
66
67 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg': {
68 protocol: 'http:',
69 slashes: true,
70 host: 'evil-phisher',
71 hostname: 'evil-phisher',
72 pathname: '/foo.html',
73 path: '/foo.html',
74 hash: '#h%5Ca%5Cs%5Ch?blarg',
75 href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg'
76 },
77
78 'http:\\\\evil-phisher\\foo.html': {
79 protocol: 'http:',
80 slashes: true,
81 host: 'evil-phisher',
82 hostname: 'evil-phisher',
83 pathname: '/foo.html',
84 path: '/foo.html',
85 href: 'http://evil-phisher/foo.html'
86 },
87
88 'HTTP://www.example.com/': {
89 href: 'http://www.example.com/',
90 protocol: 'http:',
91 slashes: true,
92 host: 'www.example.com',
93 hostname: 'www.example.com',
94 pathname: '/',
95 path: '/'
96 },
97
98 'HTTP://www.example.com': {
99 href: 'http://www.example.com/',
100 protocol: 'http:',
101 slashes: true,
102 host: 'www.example.com',
103 hostname: 'www.example.com',
104 pathname: '/',
105 path: '/'
106 },
107
108 'http://www.ExAmPlE.com/': {
109 href: 'http://www.example.com/',
110 protocol: 'http:',
111 slashes: true,
112 host: 'www.example.com',
113 hostname: 'www.example.com',
114 pathname: '/',
115 path: '/'
116 },
117
118 'http://user:pw@www.ExAmPlE.com/': {
119 href: 'http://user:pw@www.example.com/',
120 protocol: 'http:',
121 slashes: true,
122 auth: 'user:pw',
123 host: 'www.example.com',
124 hostname: 'www.example.com',
125 pathname: '/',
126 path: '/'
127 },
128
129 'http://USER:PW@www.ExAmPlE.com/': {
130 href: 'http://USER:PW@www.example.com/',
131 protocol: 'http:',
132 slashes: true,
133 auth: 'USER:PW',
134 host: 'www.example.com',
135 hostname: 'www.example.com',
136 pathname: '/',
137 path: '/'
138 },
139
140 'http://user@www.example.com/': {
141 href: 'http://user@www.example.com/',
142 protocol: 'http:',
143 slashes: true,
144 auth: 'user',
145 host: 'www.example.com',
146 hostname: 'www.example.com',
147 pathname: '/',
148 path: '/'
149 },
150
151 'http://user%3Apw@www.example.com/': {
152 href: 'http://user:pw@www.example.com/',
153 protocol: 'http:',
154 slashes: true,
155 auth: 'user:pw',
156 host: 'www.example.com',
157 hostname: 'www.example.com',
158 pathname: '/',
159 path: '/'
160 },
161
162 'http://x.com/path?that\'s#all, folks': {
163 href: 'http://x.com/path?that%27s#all,%20folks',
164 protocol: 'http:',
165 slashes: true,
166 host: 'x.com',
167 hostname: 'x.com',
168 search: '?that%27s',
169 query: 'that%27s',
170 pathname: '/path',
171 hash: '#all,%20folks',
172 path: '/path?that%27s'
173 },
174
175 'HTTP://X.COM/Y': {
176 href: 'http://x.com/Y',
177 protocol: 'http:',
178 slashes: true,
179 host: 'x.com',
180 hostname: 'x.com',
181 pathname: '/Y',
182 path: '/Y'
183 },
184
185 /*
186 * + not an invalid host character
187 * per https://url.spec.whatwg.org/#host-parsing
188 */
189 'http://x.y.com+a/b/c': {
190 href: 'http://x.y.com+a/b/c',
191 protocol: 'http:',
192 slashes: true,
193 host: 'x.y.com+a',
194 hostname: 'x.y.com+a',
195 pathname: '/b/c',
196 path: '/b/c'
197 },
198
199 // an unexpected invalid char in the hostname.
200 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i': {
201 href: 'http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei',
202 protocol: 'http:',
203 slashes: true,
204 host: 'x.y.com',
205 hostname: 'x.y.com',
206 pathname: ';a/b/c',
207 search: '?d=e',
208 query: 'd=e',
209 hash: '#f%20g%3Ch%3Ei',
210 path: ';a/b/c?d=e'
211 },
212
213 // make sure that we don't accidentally lcast the path parts.
214 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i': {
215 href: 'http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
216 protocol: 'http:',
217 slashes: true,
218 host: 'x.y.com',
219 hostname: 'x.y.com',
220 pathname: ';A/b/c',
221 search: '?d=e',
222 query: 'd=e',
223 hash: '#f%20g%3Ch%3Ei',
224 path: ';A/b/c?d=e'
225 },
226
227 'http://x...y...#p': {
228 href: 'http://x...y.../#p',
229 protocol: 'http:',
230 slashes: true,
231 host: 'x...y...',
232 hostname: 'x...y...',
233 hash: '#p',
234 pathname: '/',
235 path: '/'
236 },
237
238 'http://x/p/"quoted"': {
239 href: 'http://x/p/%22quoted%22',
240 protocol: 'http:',
241 slashes: true,
242 host: 'x',
243 hostname: 'x',
244 pathname: '/p/%22quoted%22',
245 path: '/p/%22quoted%22'
246 },
247
248 '<http://goo.corn/bread> Is a URL!': {
249 href: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
250 pathname: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
251 path: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!'
252 },
253
254 'http://www.narwhaljs.org/blog/categories?id=news': {
255 href: 'http://www.narwhaljs.org/blog/categories?id=news',
256 protocol: 'http:',
257 slashes: true,
258 host: 'www.narwhaljs.org',
259 hostname: 'www.narwhaljs.org',
260 search: '?id=news',
261 query: 'id=news',
262 pathname: '/blog/categories',
263 path: '/blog/categories?id=news'
264 },
265
266 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=': {
267 href: 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
268 protocol: 'http:',
269 slashes: true,
270 host: 'mt0.google.com',
271 hostname: 'mt0.google.com',
272 pathname: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
273 path: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
274 },
275
276 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
277 href: 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=',
278 protocol: 'http:',
279 slashes: true,
280 host: 'mt0.google.com',
281 hostname: 'mt0.google.com',
282 search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
283 query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
284 pathname: '/vt/lyrs=m@114',
285 path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
286 },
287
288 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
289 href: 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=',
290 protocol: 'http:',
291 slashes: true,
292 host: 'mt0.google.com',
293 auth: 'user:pass',
294 hostname: 'mt0.google.com',
295 search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
296 query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
297 pathname: '/vt/lyrs=m@114',
298 path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
299 },
300
301 'file:///etc/passwd': {
302 href: 'file:///etc/passwd',
303 slashes: true,
304 protocol: 'file:',
305 pathname: '/etc/passwd',
306 hostname: '',
307 host: '',
308 path: '/etc/passwd'
309 },
310
311 'file://localhost/etc/passwd': {
312 href: 'file://localhost/etc/passwd',
313 protocol: 'file:',
314 slashes: true,
315 pathname: '/etc/passwd',
316 hostname: 'localhost',
317 host: 'localhost',
318 path: '/etc/passwd'
319 },
320
321 'file://foo/etc/passwd': {
322 href: 'file://foo/etc/passwd',
323 protocol: 'file:',
324 slashes: true,
325 pathname: '/etc/passwd',
326 hostname: 'foo',
327 host: 'foo',
328 path: '/etc/passwd'
329 },
330
331 'file:///etc/node/': {
332 href: 'file:///etc/node/',
333 slashes: true,
334 protocol: 'file:',
335 pathname: '/etc/node/',
336 hostname: '',
337 host: '',
338 path: '/etc/node/'
339 },
340
341 'file://localhost/etc/node/': {
342 href: 'file://localhost/etc/node/',
343 protocol: 'file:',
344 slashes: true,
345 pathname: '/etc/node/',
346 hostname: 'localhost',
347 host: 'localhost',
348 path: '/etc/node/'
349 },
350
351 'file://foo/etc/node/': {
352 href: 'file://foo/etc/node/',
353 protocol: 'file:',
354 slashes: true,
355 pathname: '/etc/node/',
356 hostname: 'foo',
357 host: 'foo',
358 path: '/etc/node/'
359 },
360
361 'http:/baz/../foo/bar': {
362 href: 'http:/baz/../foo/bar',
363 protocol: 'http:',
364 pathname: '/baz/../foo/bar',
365 path: '/baz/../foo/bar'
366 },
367
368 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag': {
369 href: 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag',
370 protocol: 'http:',
371 slashes: true,
372 host: 'example.com:8000',
373 auth: 'user:pass',
374 port: '8000',
375 hostname: 'example.com',
376 hash: '#frag',
377 search: '?baz=quux',
378 query: 'baz=quux',
379 pathname: '/foo/bar',
380 path: '/foo/bar?baz=quux'
381 },
382
383 '//user:pass@example.com:8000/foo/bar?baz=quux#frag': {
384 href: '//user:pass@example.com:8000/foo/bar?baz=quux#frag',
385 slashes: true,
386 host: 'example.com:8000',
387 auth: 'user:pass',
388 port: '8000',
389 hostname: 'example.com',
390 hash: '#frag',
391 search: '?baz=quux',
392 query: 'baz=quux',
393 pathname: '/foo/bar',
394 path: '/foo/bar?baz=quux'
395 },
396
397 '/foo/bar?baz=quux#frag': {
398 href: '/foo/bar?baz=quux#frag',
399 hash: '#frag',
400 search: '?baz=quux',
401 query: 'baz=quux',
402 pathname: '/foo/bar',
403 path: '/foo/bar?baz=quux'
404 },
405
406 'http:/foo/bar?baz=quux#frag': {
407 href: 'http:/foo/bar?baz=quux#frag',
408 protocol: 'http:',
409 hash: '#frag',
410 search: '?baz=quux',
411 query: 'baz=quux',
412 pathname: '/foo/bar',
413 path: '/foo/bar?baz=quux'
414 },
415
416 'mailto:foo@bar.com?subject=hello': {
417 href: 'mailto:foo@bar.com?subject=hello',
418 protocol: 'mailto:',
419 host: 'bar.com',
420 auth: 'foo',
421 hostname: 'bar.com',
422 search: '?subject=hello',
423 query: 'subject=hello',
424 path: '?subject=hello'
425 },
426
427 'javascript:alert(\'hello\');': {
428 href: 'javascript:alert(\'hello\');',
429 protocol: 'javascript:',
430 pathname: 'alert(\'hello\');',
431 path: 'alert(\'hello\');'
432 },
433
434 'xmpp:isaacschlueter@jabber.org': {
435 href: 'xmpp:isaacschlueter@jabber.org',
436 protocol: 'xmpp:',
437 host: 'jabber.org',
438 auth: 'isaacschlueter',
439 hostname: 'jabber.org'
440 },
441
442 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar': {
443 href: 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar',
444 protocol: 'http:',
445 slashes: true,
446 host: '127.0.0.1:8080',
447 auth: 'atpass:foo@bar',
448 hostname: '127.0.0.1',
449 port: '8080',
450 pathname: '/path',
451 search: '?search=foo',
452 query: 'search=foo',
453 hash: '#bar',
454 path: '/path?search=foo'
455 },
456
457 'svn+ssh://foo/bar': {
458 href: 'svn+ssh://foo/bar',
459 host: 'foo',
460 hostname: 'foo',
461 protocol: 'svn+ssh:',
462 pathname: '/bar',
463 path: '/bar',
464 slashes: true
465 },
466
467 'dash-test://foo/bar': {
468 href: 'dash-test://foo/bar',
469 host: 'foo',
470 hostname: 'foo',
471 protocol: 'dash-test:',
472 pathname: '/bar',
473 path: '/bar',
474 slashes: true
475 },
476
477 'dash-test:foo/bar': {
478 href: 'dash-test:foo/bar',
479 host: 'foo',
480 hostname: 'foo',
481 protocol: 'dash-test:',
482 pathname: '/bar',
483 path: '/bar'
484 },
485
486 'dot.test://foo/bar': {
487 href: 'dot.test://foo/bar',
488 host: 'foo',
489 hostname: 'foo',
490 protocol: 'dot.test:',
491 pathname: '/bar',
492 path: '/bar',
493 slashes: true
494 },
495
496 'dot.test:foo/bar': {
497 href: 'dot.test:foo/bar',
498 host: 'foo',
499 hostname: 'foo',
500 protocol: 'dot.test:',
501 pathname: '/bar',
502 path: '/bar'
503 },
504
505 // IDNA tests
506 'http://www.日本語.com/': {
507 href: 'http://www.xn--wgv71a119e.com/',
508 protocol: 'http:',
509 slashes: true,
510 host: 'www.xn--wgv71a119e.com',
511 hostname: 'www.xn--wgv71a119e.com',
512 pathname: '/',
513 path: '/'
514 },
515
516 'http://example.Bücher.com/': {
517 href: 'http://example.xn--bcher-kva.com/',
518 protocol: 'http:',
519 slashes: true,
520 host: 'example.xn--bcher-kva.com',
521 hostname: 'example.xn--bcher-kva.com',
522 pathname: '/',
523 path: '/'
524 },
525
526 'http://www.Äffchen.com/': {
527 href: 'http://www.xn--ffchen-9ta.com/',
528 protocol: 'http:',
529 slashes: true,
530 host: 'www.xn--ffchen-9ta.com',
531 hostname: 'www.xn--ffchen-9ta.com',
532 pathname: '/',
533 path: '/'
534 },
535
536 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i': {
537 href: 'http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
538 protocol: 'http:',
539 slashes: true,
540 host: 'www.xn--ffchen-9ta.com',
541 hostname: 'www.xn--ffchen-9ta.com',
542 pathname: ';A/b/c',
543 search: '?d=e',
544 query: 'd=e',
545 hash: '#f%20g%3Ch%3Ei',
546 path: ';A/b/c?d=e'
547 },
548
549 'http://SÉLIER.COM/': {
550 href: 'http://xn--slier-bsa.com/',
551 protocol: 'http:',
552 slashes: true,
553 host: 'xn--slier-bsa.com',
554 hostname: 'xn--slier-bsa.com',
555 pathname: '/',
556 path: '/'
557 },
558
559 'http://ليهمابتكلموشعربي؟.ي؟/': {
560 href: 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/',
561 protocol: 'http:',
562 slashes: true,
563 host: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
564 hostname: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
565 pathname: '/',
566 path: '/'
567 },
568
569 'http://➡.ws/➡': {
570 href: 'http://xn--hgi.ws/➡',
571 protocol: 'http:',
572 slashes: true,
573 host: 'xn--hgi.ws',
574 hostname: 'xn--hgi.ws',
575 pathname: '/➡',
576 path: '/➡'
577 },
578
579 'http://bucket_name.s3.amazonaws.com/image.jpg': {
580 protocol: 'http:',
581 slashes: true,
582 host: 'bucket_name.s3.amazonaws.com',
583 hostname: 'bucket_name.s3.amazonaws.com',
584 pathname: '/image.jpg',
585 href: 'http://bucket_name.s3.amazonaws.com/image.jpg',
586 path: '/image.jpg'
587 },
588
589 'git+http://github.com/joyent/node.git': {
590 protocol: 'git+http:',
591 slashes: true,
592 host: 'github.com',
593 hostname: 'github.com',
594 pathname: '/joyent/node.git',
595 path: '/joyent/node.git',
596 href: 'git+http://github.com/joyent/node.git'
597 },
598
599 /*
600 * if local1@domain1 is uses as a relative URL it may
601 * be parse into auth@hostname, but here there is no
602 * way to make it work in url.parse, I add the test to be explicit
603 */
604 'local1@domain1': {
605 pathname: 'local1@domain1',
606 path: 'local1@domain1',
607 href: 'local1@domain1'
608 },
609
610 /*
611 * While this may seem counter-intuitive, a browser will parse
612 * <a href='www.google.com'> as a path.
613 */
614 'www.example.com': {
615 href: 'www.example.com',
616 pathname: 'www.example.com',
617 path: 'www.example.com'
618 },
619
620 // ipv6 support
621 '[fe80::1]': {
622 href: '[fe80::1]',
623 pathname: '[fe80::1]',
624 path: '[fe80::1]'
625 },
626
627 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': {
628 protocol: 'coap:',
629 slashes: true,
630 host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]',
631 hostname: 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
632 href: 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/',
633 pathname: '/',
634 path: '/'
635 },
636
637 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': {
638 protocol: 'coap:',
639 slashes: true,
640 host: '[1080:0:0:0:8:800:200c:417a]:61616',
641 port: '61616',
642 hostname: '1080:0:0:0:8:800:200c:417a',
643 href: 'coap://[1080:0:0:0:8:800:200c:417a]:61616/',
644 pathname: '/',
645 path: '/'
646 },
647
648 'http://user:password@[3ffe:2a00:100:7031::1]:8080': {
649 protocol: 'http:',
650 slashes: true,
651 auth: 'user:password',
652 host: '[3ffe:2a00:100:7031::1]:8080',
653 port: '8080',
654 hostname: '3ffe:2a00:100:7031::1',
655 href: 'http://user:password@[3ffe:2a00:100:7031::1]:8080/',
656 pathname: '/',
657 path: '/'
658 },
659
660 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': {
661 protocol: 'coap:',
662 slashes: true,
663 auth: 'u:p',
664 host: '[::192.9.5.5]:61616',
665 port: '61616',
666 hostname: '::192.9.5.5',
667 href: 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature',
668 search: '?n=Temperature',
669 query: 'n=Temperature',
670 pathname: '/.well-known/r',
671 path: '/.well-known/r?n=Temperature'
672 },
673
674 // empty port
675 'http://example.com:': {
676 protocol: 'http:',
677 slashes: true,
678 host: 'example.com',
679 hostname: 'example.com',
680 href: 'http://example.com/',
681 pathname: '/',
682 path: '/'
683 },
684
685 'http://example.com:/a/b.html': {
686 protocol: 'http:',
687 slashes: true,
688 host: 'example.com',
689 hostname: 'example.com',
690 href: 'http://example.com/a/b.html',
691 pathname: '/a/b.html',
692 path: '/a/b.html'
693 },
694
695 'http://example.com:?a=b': {
696 protocol: 'http:',
697 slashes: true,
698 host: 'example.com',
699 hostname: 'example.com',
700 href: 'http://example.com/?a=b',
701 search: '?a=b',
702 query: 'a=b',
703 pathname: '/',
704 path: '/?a=b'
705 },
706
707 'http://example.com:#abc': {
708 protocol: 'http:',
709 slashes: true,
710 host: 'example.com',
711 hostname: 'example.com',
712 href: 'http://example.com/#abc',
713 hash: '#abc',
714 pathname: '/',
715 path: '/'
716 },
717
718 'http://[fe80::1]:/a/b?a=b#abc': {
719 protocol: 'http:',
720 slashes: true,
721 host: '[fe80::1]',
722 hostname: 'fe80::1',
723 href: 'http://[fe80::1]/a/b?a=b#abc',
724 search: '?a=b',
725 query: 'a=b',
726 hash: '#abc',
727 pathname: '/a/b',
728 path: '/a/b?a=b'
729 },
730
731 'http://-lovemonsterz.tumblr.com/rss': {
732 protocol: 'http:',
733 slashes: true,
734 host: '-lovemonsterz.tumblr.com',
735 hostname: '-lovemonsterz.tumblr.com',
736 href: 'http://-lovemonsterz.tumblr.com/rss',
737 pathname: '/rss',
738 path: '/rss'
739 },
740
741 'http://-lovemonsterz.tumblr.com:80/rss': {
742 protocol: 'http:',
743 slashes: true,
744 port: '80',
745 host: '-lovemonsterz.tumblr.com:80',
746 hostname: '-lovemonsterz.tumblr.com',
747 href: 'http://-lovemonsterz.tumblr.com:80/rss',
748 pathname: '/rss',
749 path: '/rss'
750 },
751
752 'http://user:pass@-lovemonsterz.tumblr.com/rss': {
753 protocol: 'http:',
754 slashes: true,
755 auth: 'user:pass',
756 host: '-lovemonsterz.tumblr.com',
757 hostname: '-lovemonsterz.tumblr.com',
758 href: 'http://user:pass@-lovemonsterz.tumblr.com/rss',
759 pathname: '/rss',
760 path: '/rss'
761 },
762
763 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': {
764 protocol: 'http:',
765 slashes: true,
766 auth: 'user:pass',
767 port: '80',
768 host: '-lovemonsterz.tumblr.com:80',
769 hostname: '-lovemonsterz.tumblr.com',
770 href: 'http://user:pass@-lovemonsterz.tumblr.com:80/rss',
771 pathname: '/rss',
772 path: '/rss'
773 },
774
775 'http://_jabber._tcp.google.com/test': {
776 protocol: 'http:',
777 slashes: true,
778 host: '_jabber._tcp.google.com',
779 hostname: '_jabber._tcp.google.com',
780 href: 'http://_jabber._tcp.google.com/test',
781 pathname: '/test',
782 path: '/test'
783 },
784
785 'http://user:pass@_jabber._tcp.google.com/test': {
786 protocol: 'http:',
787 slashes: true,
788 auth: 'user:pass',
789 host: '_jabber._tcp.google.com',
790 hostname: '_jabber._tcp.google.com',
791 href: 'http://user:pass@_jabber._tcp.google.com/test',
792 pathname: '/test',
793 path: '/test'
794 },
795
796 'http://_jabber._tcp.google.com:80/test': {
797 protocol: 'http:',
798 slashes: true,
799 port: '80',
800 host: '_jabber._tcp.google.com:80',
801 hostname: '_jabber._tcp.google.com',
802 href: 'http://_jabber._tcp.google.com:80/test',
803 pathname: '/test',
804 path: '/test'
805 },
806
807 'http://user:pass@_jabber._tcp.google.com:80/test': {
808 protocol: 'http:',
809 slashes: true,
810 auth: 'user:pass',
811 port: '80',
812 host: '_jabber._tcp.google.com:80',
813 hostname: '_jabber._tcp.google.com',
814 href: 'http://user:pass@_jabber._tcp.google.com:80/test',
815 pathname: '/test',
816 path: '/test'
817 },
818
819 'http://x:1/\' <>"`/{}|\\^~`/': {
820 protocol: 'http:',
821 slashes: true,
822 host: 'x:1',
823 port: '1',
824 hostname: 'x',
825 pathname: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
826 path: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
827 href: 'http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/'
828 },
829
830 'http://a@b@c/': {
831 protocol: 'http:',
832 slashes: true,
833 auth: 'a@b',
834 host: 'c',
835 hostname: 'c',
836 href: 'http://a%40b@c/',
837 path: '/',
838 pathname: '/'
839 },
840
841 'http://a@b?@c': {
842 protocol: 'http:',
843 slashes: true,
844 auth: 'a',
845 host: 'b',
846 hostname: 'b',
847 href: 'http://a@b/?@c',
848 path: '/?@c',
849 pathname: '/',
850 search: '?@c',
851 query: '@c'
852 },
853
854 'http://a\r" \t\n<\'b:b@c\r\nd/e?f': {
855 protocol: 'http:',
856 slashes: true,
857 auth: 'a\r" \t\n<\'b:b',
858 host: 'c',
859 port: null,
860 hostname: 'c',
861 hash: null,
862 search: '?f',
863 query: 'f',
864 pathname: '%0D%0Ad/e',
865 path: '%0D%0Ad/e?f',
866 href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f'
867 },
868
869 // git urls used by npm
870 'git+ssh://git@github.com:npm/npm': {
871 protocol: 'git+ssh:',
872 slashes: true,
873 auth: 'git',
874 host: 'github.com',
875 port: null,
876 hostname: 'github.com',
877 hash: null,
878 search: null,
879 query: null,
880 pathname: '/:npm/npm',
881 path: '/:npm/npm',
882 href: 'git+ssh://git@github.com/:npm/npm'
883 }
884
885};
886
887Object.keys(parseTests).forEach(function (u) {
888 test('parse(' + u + ')', function () {
889 var actual = url.parse(u);
890 var spaced = url.parse(' \t ' + u + '\n\t');
891 var expected = parseTests[u];
892
893 Object.keys(actual).forEach(function (i) {
894 if (expected[i] === undefined && actual[i] === null) {
895 expected[i] = null;
896 }
897 });
898
899 assert.deepEqual(actual, expected);
900 assert.deepEqual(spaced, expected);
901
902 var expected = parseTests[u].href,
903 actual = url.format(parseTests[u]);
904
905 assert.equal(actual, expected, 'format(' + u + ') == ' + u + '\nactual:' + actual);
906 });
907});
908
909var parseTestsWithQueryString = {
910 '/foo/bar?baz=quux#frag': {
911 href: '/foo/bar?baz=quux#frag',
912 hash: '#frag',
913 search: '?baz=quux',
914 query: {
915 baz: 'quux'
916 },
917 pathname: '/foo/bar',
918 path: '/foo/bar?baz=quux'
919 },
920 'http://example.com': {
921 href: 'http://example.com/',
922 protocol: 'http:',
923 slashes: true,
924 host: 'example.com',
925 hostname: 'example.com',
926 query: {},
927 search: '',
928 pathname: '/',
929 path: '/'
930 },
931 '/example': {
932 protocol: null,
933 slashes: null,
934 auth: null,
935 host: null,
936 port: null,
937 hostname: null,
938 hash: null,
939 search: '',
940 query: {},
941 pathname: '/example',
942 path: '/example',
943 href: '/example'
944 },
945 '/example?query=value': {
946 protocol: null,
947 slashes: null,
948 auth: null,
949 host: null,
950 port: null,
951 hostname: null,
952 hash: null,
953 search: '?query=value',
954 query: { query: 'value' },
955 pathname: '/example',
956 path: '/example?query=value',
957 href: '/example?query=value'
958 }
959};
960
961Object.keys(parseTestsWithQueryString).forEach(function (u) {
962 test('parse(' + u + ')', function () {
963 var actual = url.parse(u, true);
964 var expected = parseTestsWithQueryString[u];
965 for (var i in actual) {
966 if (actual[i] === null && expected[i] === undefined) {
967 expected[i] = null;
968 }
969 }
970
971 assert.deepEqual(actual, expected);
972 });
973});
974
975/*
976 * some extra formatting tests, just to verify
977 * that it'll format slightly wonky content to a valid url.
978 */
979var formatTests = {
980 'http://example.com?': {
981 href: 'http://example.com/?',
982 protocol: 'http:',
983 slashes: true,
984 host: 'example.com',
985 hostname: 'example.com',
986 search: '?',
987 query: {},
988 pathname: '/'
989 },
990 'http://example.com?foo=bar#frag': {
991 href: 'http://example.com/?foo=bar#frag',
992 protocol: 'http:',
993 host: 'example.com',
994 hostname: 'example.com',
995 hash: '#frag',
996 search: '?foo=bar',
997 query: 'foo=bar',
998 pathname: '/'
999 },
1000 'http://example.com?foo=@bar#frag': {
1001 href: 'http://example.com/?foo=@bar#frag',
1002 protocol: 'http:',
1003 host: 'example.com',
1004 hostname: 'example.com',
1005 hash: '#frag',
1006 search: '?foo=@bar',
1007 query: 'foo=@bar',
1008 pathname: '/'
1009 },
1010 'http://example.com?foo=/bar/#frag': {
1011 href: 'http://example.com/?foo=/bar/#frag',
1012 protocol: 'http:',
1013 host: 'example.com',
1014 hostname: 'example.com',
1015 hash: '#frag',
1016 search: '?foo=/bar/',
1017 query: 'foo=/bar/',
1018 pathname: '/'
1019 },
1020 'http://example.com?foo=?bar/#frag': {
1021 href: 'http://example.com/?foo=?bar/#frag',
1022 protocol: 'http:',
1023 host: 'example.com',
1024 hostname: 'example.com',
1025 hash: '#frag',
1026 search: '?foo=?bar/',
1027 query: 'foo=?bar/',
1028 pathname: '/'
1029 },
1030 'http://example.com#frag=?bar/#frag': {
1031 href: 'http://example.com/#frag=?bar/#frag',
1032 protocol: 'http:',
1033 host: 'example.com',
1034 hostname: 'example.com',
1035 hash: '#frag=?bar/#frag',
1036 pathname: '/'
1037 },
1038 'http://google.com" onload="alert(42)/': {
1039 href: 'http://google.com/%22%20onload=%22alert(42)/',
1040 protocol: 'http:',
1041 host: 'google.com',
1042 pathname: '/%22%20onload=%22alert(42)/'
1043 },
1044 'http://a.com/a/b/c?s#h': {
1045 href: 'http://a.com/a/b/c?s#h',
1046 protocol: 'http',
1047 host: 'a.com',
1048 pathname: 'a/b/c',
1049 hash: 'h',
1050 search: 's'
1051 },
1052 'xmpp:isaacschlueter@jabber.org': {
1053 href: 'xmpp:isaacschlueter@jabber.org',
1054 protocol: 'xmpp:',
1055 host: 'jabber.org',
1056 auth: 'isaacschlueter',
1057 hostname: 'jabber.org'
1058 },
1059 'http://atpass:foo%40bar@127.0.0.1/': {
1060 href: 'http://atpass:foo%40bar@127.0.0.1/',
1061 auth: 'atpass:foo@bar',
1062 hostname: '127.0.0.1',
1063 protocol: 'http:',
1064 pathname: '/'
1065 },
1066 'http://atslash%2F%40:%2F%40@foo/': {
1067 href: 'http://atslash%2F%40:%2F%40@foo/',
1068 auth: 'atslash/@:/@',
1069 hostname: 'foo',
1070 protocol: 'http:',
1071 pathname: '/'
1072 },
1073 'svn+ssh://foo/bar': {
1074 href: 'svn+ssh://foo/bar',
1075 hostname: 'foo',
1076 protocol: 'svn+ssh:',
1077 pathname: '/bar',
1078 slashes: true
1079 },
1080 'dash-test://foo/bar': {
1081 href: 'dash-test://foo/bar',
1082 hostname: 'foo',
1083 protocol: 'dash-test:',
1084 pathname: '/bar',
1085 slashes: true
1086 },
1087 'dash-test:foo/bar': {
1088 href: 'dash-test:foo/bar',
1089 hostname: 'foo',
1090 protocol: 'dash-test:',
1091 pathname: '/bar'
1092 },
1093 'dot.test://foo/bar': {
1094 href: 'dot.test://foo/bar',
1095 hostname: 'foo',
1096 protocol: 'dot.test:',
1097 pathname: '/bar',
1098 slashes: true
1099 },
1100 'dot.test:foo/bar': {
1101 href: 'dot.test:foo/bar',
1102 hostname: 'foo',
1103 protocol: 'dot.test:',
1104 pathname: '/bar'
1105 },
1106 // ipv6 support
1107 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
1108 href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
1109 protocol: 'coap:',
1110 auth: 'u:p',
1111 hostname: '::1',
1112 port: '61616',
1113 pathname: '/.well-known/r',
1114 search: 'n=Temperature'
1115 },
1116 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
1117 href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
1118 protocol: 'coap',
1119 host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
1120 pathname: '/s/stopButton'
1121 },
1122
1123 /*
1124 * encode context-specific delimiters in path and query, but do not touch
1125 * other non-delimiter chars like `%`.
1126 * <https://github.com/joyent/node/issues/4082>
1127 */
1128
1129 // `#`,`?` in path
1130 '/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
1131 href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
1132 pathname: '/path/to/%#?+=&.txt',
1133 query: {
1134 foo: 'theA1'
1135 },
1136 hash: '#bar'
1137 },
1138
1139 // `#`,`?` in path + `#` in query
1140 '/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
1141 href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
1142 pathname: '/path/to/%#?+=&.txt',
1143 query: {
1144 foo: 'the#1'
1145 },
1146 hash: '#bar'
1147 },
1148
1149 // `?` and `#` in path and search
1150 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
1151 href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
1152 protocol: 'http:',
1153 hostname: 'ex.com',
1154 hash: '#frag',
1155 search: '?abc=the#1?&foo=bar',
1156 pathname: '/foo?100%m#r'
1157 },
1158
1159 // `?` and `#` in search only
1160 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
1161 href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
1162 protocol: 'http:',
1163 hostname: 'ex.com',
1164 hash: '#frag',
1165 search: '?abc=the#1?&foo=bar',
1166 pathname: '/fooA100%mBr'
1167 },
1168
1169 // colons in keys
1170 'https://cdpn.io/test?custom%3Aid=12': {
1171 href: 'https://cdpn.io/test?custom%3Aid=12',
1172 protocol: 'https:',
1173 hostname: 'cdpn.io',
1174 hash: '',
1175 search: '?custom%3Aid=12',
1176 pathname: '/test',
1177 query: {
1178 'custom:id': '12'
1179 }
1180 }
1181};
1182
1183Object.keys(formatTests).forEach(function (u) {
1184 test('format(' + u + ')', function () {
1185 var expect = formatTests[u].href;
1186 delete formatTests[u].href;
1187 var actual = url.format(u);
1188 var actualObj = url.format(formatTests[u]);
1189 assert.equal(actual, expect, 'wonky format(' + u + ') == ' + expect + '\nactual:' + actual);
1190 assert.equal(actualObj, expect, 'wonky format(' + JSON.stringify(formatTests[u]) + ') == ' + expect + '\nactual: ' + actualObj);
1191 });
1192});
1193
1194/*
1195 *[from, path, expected]
1196 */
1197var relativeTests = [
1198 [
1199 '/foo/bar/baz', 'quux', '/foo/bar/quux'
1200 ],
1201 [
1202 '/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'
1203 ],
1204 [
1205 '/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'
1206 ],
1207 [
1208 '/foo/bar/baz', '../quux/baz', '/foo/quux/baz'
1209 ],
1210 [
1211 '/foo/bar/baz', '/bar', '/bar'
1212 ],
1213 [
1214 '/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'
1215 ],
1216 [
1217 '/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'
1218 ],
1219 [
1220 '/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'
1221 ],
1222 [
1223 '/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'
1224 ],
1225 [
1226 '/foo', '.', '/'
1227 ],
1228 [
1229 '/foo', '..', '/'
1230 ],
1231 [
1232 '/foo/', '.', '/foo/'
1233 ],
1234 [
1235 '/foo/', '..', '/'
1236 ],
1237 [
1238 '/foo/bar', '.', '/foo/'
1239 ],
1240 [
1241 '/foo/bar', '..', '/'
1242 ],
1243 [
1244 '/foo/bar/', '.', '/foo/bar/'
1245 ],
1246 [
1247 '/foo/bar/', '..', '/foo/'
1248 ],
1249 [
1250 'foo/bar', '../../../baz', '../../baz'
1251 ],
1252 [
1253 'foo/bar/', '../../../baz', '../baz'
1254 ],
1255 [
1256 'http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'
1257 ],
1258 [
1259 'http://example.com/b//c//d;p?q#blarg',
1260 'https:/p/a/t/h?s#hash2',
1261 'https://p/a/t/h?s#hash2'
1262 ],
1263 [
1264 'http://example.com/b//c//d;p?q#blarg',
1265 'https://u:p@h.com/p/a/t/h?s#hash2',
1266 'https://u:p@h.com/p/a/t/h?s#hash2'
1267 ],
1268 [
1269 'http://example.com/b//c//d;p?q#blarg',
1270 'https:/a/b/c/d',
1271 'https://a/b/c/d'
1272 ],
1273 [
1274 'http://example.com/b//c//d;p?q#blarg',
1275 'http:#hash2',
1276 'http://example.com/b//c//d;p?q#hash2'
1277 ],
1278 [
1279 'http://example.com/b//c//d;p?q#blarg',
1280 'http:/p/a/t/h?s#hash2',
1281 'http://example.com/p/a/t/h?s#hash2'
1282 ],
1283 [
1284 'http://example.com/b//c//d;p?q#blarg',
1285 'http://u:p@h.com/p/a/t/h?s#hash2',
1286 'http://u:p@h.com/p/a/t/h?s#hash2'
1287 ],
1288 [
1289 'http://example.com/b//c//d;p?q#blarg',
1290 'http:/a/b/c/d',
1291 'http://example.com/a/b/c/d'
1292 ],
1293 [
1294 '/foo/bar/baz', '/../etc/passwd', '/etc/passwd'
1295 ]
1296];
1297
1298relativeTests.forEach(function (relativeTest) {
1299 test('resolve(' + [relativeTest[0], relativeTest[1]] + ')', function () {
1300 var a = url.resolve(relativeTest[0], relativeTest[1]),
1301 e = relativeTest[2];
1302 assert.equal(a, e, 'resolve(' + [relativeTest[0], relativeTest[1]] + ') == ' + e + '\n actual=' + a);
1303 });
1304});
1305
1306// https://github.com/joyent/node/issues/568
1307[
1308 undefined,
1309 null,
1310 true,
1311 false,
1312 0.0,
1313 0,
1314 [],
1315 {}
1316].forEach(function (val) {
1317 test('parse(' + val + ')', function () {
1318 assert['throws'](function () { url.parse(val); }, TypeError);
1319 });
1320});
1321
1322/*
1323 *
1324 * Tests below taken from Chiron
1325 * http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js
1326 *
1327 * Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
1328 * used with permission under MIT License
1329 *
1330 * Changes marked with @isaacs
1331 */
1332
1333var bases = [
1334 'http://a/b/c/d;p?q',
1335 'http://a/b/c/d;p?q=1/2',
1336 'http://a/b/c/d;p=1/2?q',
1337 'fred:///s//a/b/c',
1338 'http:///s//a/b/c'
1339];
1340
1341// [to, from, result]
1342var relativeTests2 = [
1343 // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html
1344 [
1345 '../c', 'foo:a/b', 'foo:c'
1346 ],
1347 [
1348 'foo:.', 'foo:a', 'foo:'
1349 ],
1350 [
1351 '/foo/../../../bar', 'zz:abc', 'zz:/bar'
1352 ],
1353 [
1354 '/foo/../bar', 'zz:abc', 'zz:/bar'
1355 ],
1356 // @isaacs Disagree. Not how web browsers resolve this.
1357 [
1358 'foo/../../../bar', 'zz:abc', 'zz:bar'
1359 ],
1360 // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added
1361 [
1362 'foo/../bar', 'zz:abc', 'zz:bar'
1363 ],
1364 [
1365 'zz:.', 'zz:abc', 'zz:'
1366 ],
1367 [
1368 '/.', bases[0], 'http://a/'
1369 ],
1370 [
1371 '/.foo', bases[0], 'http://a/.foo'
1372 ],
1373 [
1374 '.foo', bases[0], 'http://a/b/c/.foo'
1375 ],
1376
1377 /*
1378 * http://gbiv.com/protocols/uri/test/rel_examples1.html
1379 * examples from RFC 2396
1380 */
1381 [
1382 'g:h', bases[0], 'g:h'
1383 ],
1384 [
1385 'g', bases[0], 'http://a/b/c/g'
1386 ],
1387 [
1388 './g', bases[0], 'http://a/b/c/g'
1389 ],
1390 [
1391 'g/', bases[0], 'http://a/b/c/g/'
1392 ],
1393 [
1394 '/g', bases[0], 'http://a/g'
1395 ],
1396 [
1397 '//g', bases[0], 'http://g/'
1398 ],
1399 /*
1400 * changed with RFC 2396bis
1401 * ('?y', bases[0], 'http://a/b/c/d;p?y'],
1402 */
1403 [
1404 '?y', bases[0], 'http://a/b/c/d;p?y'
1405 ],
1406 [
1407 'g?y', bases[0], 'http://a/b/c/g?y'
1408 ],
1409 /*
1410 * changed with RFC 2396bis
1411 * ('#s', bases[0], CURRENT_DOC_URI + '#s'],
1412 */
1413 [
1414 '#s', bases[0], 'http://a/b/c/d;p?q#s'
1415 ],
1416 [
1417 'g#s', bases[0], 'http://a/b/c/g#s'
1418 ],
1419 [
1420 'g?y#s', bases[0], 'http://a/b/c/g?y#s'
1421 ],
1422 [
1423 ';x', bases[0], 'http://a/b/c/;x'
1424 ],
1425 [
1426 'g;x', bases[0], 'http://a/b/c/g;x'
1427 ],
1428 [
1429 'g;x?y#s', bases[0], 'http://a/b/c/g;x?y#s'
1430 ],
1431 /*
1432 * changed with RFC 2396bis
1433 * ('', bases[0], CURRENT_DOC_URI],
1434 */
1435 [
1436 '', bases[0], 'http://a/b/c/d;p?q'
1437 ],
1438 [
1439 '.', bases[0], 'http://a/b/c/'
1440 ],
1441 [
1442 './', bases[0], 'http://a/b/c/'
1443 ],
1444 [
1445 '..', bases[0], 'http://a/b/'
1446 ],
1447 [
1448 '../', bases[0], 'http://a/b/'
1449 ],
1450 [
1451 '../g', bases[0], 'http://a/b/g'
1452 ],
1453 [
1454 '../..', bases[0], 'http://a/'
1455 ],
1456 [
1457 '../../', bases[0], 'http://a/'
1458 ],
1459 [
1460 '../../g', bases[0], 'http://a/g'
1461 ],
1462 [
1463 '../../../g', bases[0], ('http://a/../g', 'http://a/g')
1464 ],
1465 [
1466 '../../../../g', bases[0], ('http://a/../../g', 'http://a/g')
1467 ],
1468 /*
1469 * changed with RFC 2396bis
1470 * ('/./g', bases[0], 'http://a/./g'],
1471 */
1472 [
1473 '/./g', bases[0], 'http://a/g'
1474 ],
1475 /*
1476 * changed with RFC 2396bis
1477 * ('/../g', bases[0], 'http://a/../g'],
1478 */
1479 [
1480 '/../g', bases[0], 'http://a/g'
1481 ],
1482 [
1483 'g.', bases[0], 'http://a/b/c/g.'
1484 ],
1485 [
1486 '.g', bases[0], 'http://a/b/c/.g'
1487 ],
1488 [
1489 'g..', bases[0], 'http://a/b/c/g..'
1490 ],
1491 [
1492 '..g', bases[0], 'http://a/b/c/..g'
1493 ],
1494 [
1495 './../g', bases[0], 'http://a/b/g'
1496 ],
1497 [
1498 './g/.', bases[0], 'http://a/b/c/g/'
1499 ],
1500 [
1501 'g/./h', bases[0], 'http://a/b/c/g/h'
1502 ],
1503 [
1504 'g/../h', bases[0], 'http://a/b/c/h'
1505 ],
1506 [
1507 'g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'
1508 ],
1509 [
1510 'g;x=1/../y', bases[0], 'http://a/b/c/y'
1511 ],
1512 [
1513 'g?y/./x', bases[0], 'http://a/b/c/g?y/./x'
1514 ],
1515 [
1516 'g?y/../x', bases[0], 'http://a/b/c/g?y/../x'
1517 ],
1518 [
1519 'g#s/./x', bases[0], 'http://a/b/c/g#s/./x'
1520 ],
1521 [
1522 'g#s/../x', bases[0], 'http://a/b/c/g#s/../x'
1523 ],
1524 [
1525 'http:g', bases[0], ('http:g', 'http://a/b/c/g')
1526 ],
1527 [
1528 'http:', bases[0], ('http:', bases[0])
1529 ],
1530 // not sure where this one originated
1531 [
1532 '/a/b/c/./../../g', bases[0], 'http://a/a/g'
1533 ],
1534
1535 /*
1536 * http://gbiv.com/protocols/uri/test/rel_examples2.html
1537 * slashes in base URI's query args
1538 */
1539 [
1540 'g', bases[1], 'http://a/b/c/g'
1541 ],
1542 [
1543 './g', bases[1], 'http://a/b/c/g'
1544 ],
1545 [
1546 'g/', bases[1], 'http://a/b/c/g/'
1547 ],
1548 [
1549 '/g', bases[1], 'http://a/g'
1550 ],
1551 [
1552 '//g', bases[1], 'http://g/'
1553 ],
1554 /*
1555 * changed in RFC 2396bis
1556 * ('?y', bases[1], 'http://a/b/c/?y'],
1557 */
1558 [
1559 '?y', bases[1], 'http://a/b/c/d;p?y'
1560 ],
1561 [
1562 'g?y', bases[1], 'http://a/b/c/g?y'
1563 ],
1564 [
1565 'g?y/./x', bases[1], 'http://a/b/c/g?y/./x'
1566 ],
1567 [
1568 'g?y/../x', bases[1], 'http://a/b/c/g?y/../x'
1569 ],
1570 [
1571 'g#s', bases[1], 'http://a/b/c/g#s'
1572 ],
1573 [
1574 'g#s/./x', bases[1], 'http://a/b/c/g#s/./x'
1575 ],
1576 [
1577 'g#s/../x', bases[1], 'http://a/b/c/g#s/../x'
1578 ],
1579 [
1580 './', bases[1], 'http://a/b/c/'
1581 ],
1582 [
1583 '../', bases[1], 'http://a/b/'
1584 ],
1585 [
1586 '../g', bases[1], 'http://a/b/g'
1587 ],
1588 [
1589 '../../', bases[1], 'http://a/'
1590 ],
1591 [
1592 '../../g', bases[1], 'http://a/g'
1593 ],
1594
1595 /*
1596 * http://gbiv.com/protocols/uri/test/rel_examples3.html
1597 * slashes in path params
1598 * all of these changed in RFC 2396bis
1599 */
1600 [
1601 'g', bases[2], 'http://a/b/c/d;p=1/g'
1602 ],
1603 [
1604 './g', bases[2], 'http://a/b/c/d;p=1/g'
1605 ],
1606 [
1607 'g/', bases[2], 'http://a/b/c/d;p=1/g/'
1608 ],
1609 [
1610 'g?y', bases[2], 'http://a/b/c/d;p=1/g?y'
1611 ],
1612 [
1613 ';x', bases[2], 'http://a/b/c/d;p=1/;x'
1614 ],
1615 [
1616 'g;x', bases[2], 'http://a/b/c/d;p=1/g;x'
1617 ],
1618 [
1619 'g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'
1620 ],
1621 [
1622 'g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'
1623 ],
1624 [
1625 './', bases[2], 'http://a/b/c/d;p=1/'
1626 ],
1627 [
1628 '../', bases[2], 'http://a/b/c/'
1629 ],
1630 [
1631 '../g', bases[2], 'http://a/b/c/g'
1632 ],
1633 [
1634 '../../', bases[2], 'http://a/b/'
1635 ],
1636 [
1637 '../../g', bases[2], 'http://a/b/g'
1638 ],
1639
1640 /*
1641 * http://gbiv.com/protocols/uri/test/rel_examples4.html
1642 * double and triple slash, unknown scheme
1643 */
1644 [
1645 'g:h', bases[3], 'g:h'
1646 ],
1647 [
1648 'g', bases[3], 'fred:///s//a/b/g'
1649 ],
1650 [
1651 './g', bases[3], 'fred:///s//a/b/g'
1652 ],
1653 [
1654 'g/', bases[3], 'fred:///s//a/b/g/'
1655 ],
1656 [
1657 '/g', bases[3], 'fred:///g'
1658 ], // may change to fred:///s//a/g
1659 [
1660 '//g', bases[3], 'fred://g'
1661 ], // may change to fred:///s//g
1662 [
1663 '//g/x', bases[3], 'fred://g/x'
1664 ], // may change to fred:///s//g/x
1665 [
1666 '///g', bases[3], 'fred:///g'
1667 ],
1668 [
1669 './', bases[3], 'fred:///s//a/b/'
1670 ],
1671 [
1672 '../', bases[3], 'fred:///s//a/'
1673 ],
1674 [
1675 '../g', bases[3], 'fred:///s//a/g'
1676 ],
1677
1678 [
1679 '../../', bases[3], 'fred:///s//'
1680 ],
1681 [
1682 '../../g', bases[3], 'fred:///s//g'
1683 ],
1684 [
1685 '../../../g', bases[3], 'fred:///s/g'
1686 ],
1687 // may change to fred:///s//a/../../../g
1688 [
1689 '../../../../g', bases[3], 'fred:///g'
1690 ],
1691
1692 /*
1693 * http://gbiv.com/protocols/uri/test/rel_examples5.html
1694 * double and triple slash, well-known scheme
1695 */
1696 [
1697 'g:h', bases[4], 'g:h'
1698 ],
1699 [
1700 'g', bases[4], 'http:///s//a/b/g'
1701 ],
1702 [
1703 './g', bases[4], 'http:///s//a/b/g'
1704 ],
1705 [
1706 'g/', bases[4], 'http:///s//a/b/g/'
1707 ],
1708 [
1709 '/g', bases[4], 'http:///g'
1710 ], // may change to http:///s//a/g
1711 [
1712 '//g', bases[4], 'http://g/'
1713 ], // may change to http:///s//g
1714 [
1715 '//g/x', bases[4], 'http://g/x'
1716 ], // may change to http:///s//g/x
1717 [
1718 '///g', bases[4], 'http:///g'
1719 ],
1720 [
1721 './', bases[4], 'http:///s//a/b/'
1722 ],
1723 [
1724 '../', bases[4], 'http:///s//a/'
1725 ],
1726 [
1727 '../g', bases[4], 'http:///s//a/g'
1728 ],
1729 [
1730 '../../', bases[4], 'http:///s//'
1731 ],
1732 [
1733 '../../g', bases[4], 'http:///s//g'
1734 ],
1735 // may change to http:///s//a/../../g
1736 [
1737 '../../../g', bases[4], 'http:///s/g'
1738 ],
1739 // may change to http:///s//a/../../../g
1740 [
1741 '../../../../g', bases[4], 'http:///g'
1742 ],
1743
1744 // from Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py
1745 [
1746 'bar:abc', 'foo:xyz', 'bar:abc'
1747 ],
1748 [
1749 '../abc', 'http://example/x/y/z', 'http://example/x/abc'
1750 ],
1751 [
1752 'http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'
1753 ],
1754 [
1755 '../r', 'http://ex/x/y/z', 'http://ex/x/r'
1756 ],
1757 [
1758 'q/r', 'http://ex/x/y', 'http://ex/x/q/r'
1759 ],
1760 [
1761 'q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'
1762 ],
1763 [
1764 'q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'
1765 ],
1766 [
1767 'ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'
1768 ],
1769 [
1770 '', 'http://ex/x/y', 'http://ex/x/y'
1771 ],
1772 [
1773 '', 'http://ex/x/y/', 'http://ex/x/y/'
1774 ],
1775 [
1776 '', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'
1777 ],
1778 [
1779 'z/', 'http://ex/x/y/', 'http://ex/x/y/z/'
1780 ],
1781 [
1782 '#Animal',
1783 'file:/swap/test/animal.rdf',
1784 'file:/swap/test/animal.rdf#Animal'
1785 ],
1786 [
1787 '../abc', 'file:/e/x/y/z', 'file:/e/x/abc'
1788 ],
1789 [
1790 '/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'
1791 ],
1792 [
1793 '../r', 'file:/ex/x/y/z', 'file:/ex/x/r'
1794 ],
1795 [
1796 '/r', 'file:/ex/x/y/z', 'file:/r'
1797 ],
1798 [
1799 'q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'
1800 ],
1801 [
1802 'q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'
1803 ],
1804 [
1805 'q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'
1806 ],
1807 [
1808 'q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'
1809 ],
1810 [
1811 'ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'
1812 ],
1813 [
1814 '', 'file:/ex/x/y', 'file:/ex/x/y'
1815 ],
1816 [
1817 '', 'file:/ex/x/y/', 'file:/ex/x/y/'
1818 ],
1819 [
1820 '', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'
1821 ],
1822 [
1823 'z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'
1824 ],
1825 [
1826 'file://meetings.example.com/cal#m1',
1827 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3',
1828 'file://meetings.example.com/cal#m1'
1829 ],
1830 [
1831 'file://meetings.example.com/cal#m1',
1832 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3',
1833 'file://meetings.example.com/cal#m1'
1834 ],
1835 [
1836 './#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'
1837 ],
1838 [
1839 './#', 'file:/some/dir/foo', 'file:/some/dir/#'
1840 ],
1841 // Ryan Lee
1842 [
1843 './', 'http://example/x/abc.efg', 'http://example/x/'
1844 ],
1845
1846 /*
1847 * Graham Klyne's tests
1848 * http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls
1849 * 01-31 are from Connelly's cases
1850 */
1851
1852 // 32-49
1853 [
1854 './q:r', 'http://ex/x/y', 'http://ex/x/q:r'
1855 ],
1856 [
1857 './p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'
1858 ],
1859 [
1860 '?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'
1861 ],
1862 [
1863 'y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'
1864 ],
1865 [
1866 'local/qual@domain.org#frag',
1867 'mailto:local',
1868 'mailto:local/qual@domain.org#frag'
1869 ],
1870 [
1871 'more/qual2@domain2.org#frag',
1872 'mailto:local/qual1@domain1.org',
1873 'mailto:local/more/qual2@domain2.org#frag'
1874 ],
1875 [
1876 'y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'
1877 ],
1878 [
1879 '/x/y?q', 'http://ex?p', 'http://ex/x/y?q'
1880 ],
1881 [
1882 'c/d', 'foo:a/b', 'foo:a/c/d'
1883 ],
1884 [
1885 '/c/d', 'foo:a/b', 'foo:/c/d'
1886 ],
1887 [
1888 '', 'foo:a/b?c#d', 'foo:a/b?c'
1889 ],
1890 [
1891 'b/c', 'foo:a', 'foo:b/c'
1892 ],
1893 [
1894 '../b/c', 'foo:/a/y/z', 'foo:/a/b/c'
1895 ],
1896 [
1897 './b/c', 'foo:a', 'foo:b/c'
1898 ],
1899 [
1900 '/./b/c', 'foo:a', 'foo:/b/c'
1901 ],
1902 [
1903 '../../d', 'foo://a//b/c', 'foo://a/d'
1904 ],
1905 [
1906 '.', 'foo:a', 'foo:'
1907 ],
1908 [
1909 '..', 'foo:a', 'foo:'
1910 ],
1911
1912 /*
1913 * 50-57[cf. TimBL comments --
1914 * http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html,
1915 * http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html)
1916 */
1917 [
1918 'abc', 'http://example/x/y%2Fz', 'http://example/x/abc'
1919 ],
1920 [
1921 '../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'
1922 ],
1923 [
1924 '../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'
1925 ],
1926 [
1927 'abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'
1928 ],
1929 [
1930 'q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'
1931 ],
1932 [
1933 '/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'
1934 ],
1935 [
1936 '/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'
1937 ],
1938 [
1939 '/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'
1940 ],
1941
1942 // 70-77
1943 [
1944 'local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'
1945 ],
1946 [
1947 'local2@domain2?query2',
1948 'mailto:local1@domain1',
1949 'mailto:local2@domain2?query2'
1950 ],
1951 [
1952 'local2@domain2?query2',
1953 'mailto:local1@domain1?query1',
1954 'mailto:local2@domain2?query2'
1955 ],
1956 [
1957 '?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'
1958 ],
1959 [
1960 'local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'
1961 ],
1962 [
1963 '?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'
1964 ],
1965 [
1966 'http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'
1967 ],
1968 [
1969 'http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'
1970 ],
1971
1972 /*
1973 * 82-88
1974 * @isaacs Disagree. Not how browsers do it.
1975 * ['http:this', 'http://example.org/base/uri', 'http:this'],
1976 * @isaacs Added
1977 */
1978 [
1979 'http:this', 'http://example.org/base/uri', 'http://example.org/base/this'
1980 ],
1981 [
1982 'http:this', 'http:base', 'http:this'
1983 ],
1984 [
1985 './/g', 'f:/a', 'f://g'
1986 ],
1987 [
1988 'b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'
1989 ],
1990 [
1991 'm2@example.ord/c2@example.org',
1992 'mid:m@example.ord/c@example.org',
1993 'mid:m@example.ord/m2@example.ord/c2@example.org'
1994 ],
1995 [
1996 'mini1.xml',
1997 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/',
1998 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'
1999 ],
2000 [
2001 '../b/c', 'foo:a/y/z', 'foo:a/b/c'
2002 ],
2003
2004 // changeing auth
2005 [
2006 'http://diff:auth@www.example.com',
2007 'http://asdf:qwer@www.example.com',
2008 'http://diff:auth@www.example.com/'
2009 ]
2010];
2011
2012relativeTests2.forEach(function (relativeTest) {
2013 test('resolve(' + [relativeTest[1], relativeTest[0]] + ')', function () {
2014 var a = url.resolve(relativeTest[1], relativeTest[0]),
2015 e = relativeTest[2];
2016 assert.equal(a, e, 'resolve(' + [relativeTest[1], relativeTest[0]] + ') == ' + e + '\n actual=' + a);
2017 });
2018});
2019
2020/*
2021 * if format and parse are inverse operations then
2022 * resolveObject(parse(x), y) == parse(resolve(x, y))
2023 */
2024
2025// host and hostname are special, in this case a '' value is important
2026/* eslint no-unused-vars: 1 */
2027var emptyIsImportant = { host: true, hostname: '' };
2028
2029// format: [from, path, expected]
2030relativeTests.forEach(function (relativeTest) {
2031 test('resolveObject(' + [relativeTest[0], relativeTest[1]] + ')', function () {
2032 var actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]);
2033 var expected = url.parse(relativeTest[2]);
2034
2035 assert.deepEqual(actual, expected);
2036
2037 expected = relativeTest[2];
2038 actual = url.format(actual);
2039
2040 assert.equal(actual, expected, 'format(' + actual + ') == ' + expected + '\nactual:' + actual);
2041 });
2042});
2043
2044test('format with querystring', function () {
2045 var obj = { protocol: 'https:', host: 'google.com', pathname: 'test', query: { message: ['value1', 'value2'], 'custom:id': 12 } };
2046
2047 var actual = url.format(obj);
2048 var expected = nodeURL.format(obj);
2049
2050 assert.equal(actual, expected, 'format(' + actual + ') == ' + expected + '\nactual:' + actual);
2051});
2052
2053/*
2054 * format: [to, from, result]
2055 * the test: ['.//g', 'f:/a', 'f://g'] is a fundamental problem
2056 * url.parse('f:/a') does not have a host
2057 * url.resolve('f:/a', './/g') does not have a host because you have moved
2058 * down to the g directory. i.e. f: //g, however when this url is parsed
2059 * f:// will indicate that the host is g which is not the case.
2060 * it is unclear to me how to keep this information from being lost
2061 * it may be that a pathname of ////g should collapse to /g but this seems
2062 * to be a lot of work for an edge case. Right now I remove the test
2063 */
2064if (relativeTests2[181][0] === './/g' && relativeTests2[181][1] === 'f:/a' && relativeTests2[181][2] === 'f://g') {
2065 relativeTests2.splice(181, 1);
2066}
2067
2068relativeTests2.forEach(function (relativeTest) {
2069 test('resolveObject(' + [relativeTest[1], relativeTest[0]] + ')', function () {
2070 var actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]),
2071 expected = url.parse(relativeTest[2]);
2072
2073 assert.deepEqual(actual, expected);
2074
2075 var expected = relativeTest[2],
2076 actual = url.format(actual);
2077
2078 assert.equal(actual, expected, 'format(' + relativeTest[1] + ') == ' + expected + '\nactual:' + actual);
2079 });
2080});