UNPKG

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