test.js (43532B)
1 // Copyright Joyent, Inc. and other Node contributors. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to permit 8 // persons to whom the Software is furnished to do so, subject to the 9 // following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 var assert = require('assert'); 23 var util = require('util'); 24 25 var url = require('./url'); 26 27 test('god', function() { 28 29 // URLs to parse, and expected data 30 // { url : parsed } 31 var parseTests = { 32 '//some_path' : { 33 'href': '//some_path', 34 'pathname': '//some_path', 35 'path': '//some_path' 36 }, 37 38 'HTTP://www.example.com/' : { 39 'href': 'http://www.example.com/', 40 'protocol': 'http:', 41 'slashes': true, 42 'host': 'www.example.com', 43 'hostname': 'www.example.com', 44 'pathname': '/', 45 'path': '/' 46 }, 47 48 'HTTP://www.example.com' : { 49 'href': 'http://www.example.com/', 50 'protocol': 'http:', 51 'slashes': true, 52 'host': 'www.example.com', 53 'hostname': 'www.example.com', 54 'pathname': '/', 55 'path': '/' 56 }, 57 58 'http://www.ExAmPlE.com/' : { 59 'href': 'http://www.example.com/', 60 'protocol': 'http:', 61 'slashes': true, 62 'host': 'www.example.com', 63 'hostname': 'www.example.com', 64 'pathname': '/', 65 'path': '/' 66 }, 67 68 'http://user:pw@www.ExAmPlE.com/' : { 69 'href': 'http://user:pw@www.example.com/', 70 'protocol': 'http:', 71 'slashes': true, 72 'auth': 'user:pw', 73 'host': 'www.example.com', 74 'hostname': 'www.example.com', 75 'pathname': '/', 76 'path': '/' 77 }, 78 79 'http://USER:PW@www.ExAmPlE.com/' : { 80 'href': 'http://USER:PW@www.example.com/', 81 'protocol': 'http:', 82 'slashes': true, 83 'auth': 'USER:PW', 84 'host': 'www.example.com', 85 'hostname': 'www.example.com', 86 'pathname': '/', 87 'path': '/' 88 }, 89 90 'http://user@www.example.com/' : { 91 'href': 'http://user@www.example.com/', 92 'protocol': 'http:', 93 'slashes': true, 94 'auth': 'user', 95 'host': 'www.example.com', 96 'hostname': 'www.example.com', 97 'pathname': '/', 98 'path': '/' 99 }, 100 101 'http://user%3Apw@www.example.com/' : { 102 'href': 'http://user:pw@www.example.com/', 103 'protocol': 'http:', 104 'slashes': true, 105 'auth': 'user:pw', 106 'host': 'www.example.com', 107 'hostname': 'www.example.com', 108 'pathname': '/', 109 'path': '/' 110 }, 111 112 'http://x.com/path?that\'s#all, folks' : { 113 'href': 'http://x.com/path?that%27s#all,%20folks', 114 'protocol': 'http:', 115 'slashes': true, 116 'host': 'x.com', 117 'hostname': 'x.com', 118 'search': '?that%27s', 119 'query': 'that%27s', 120 'pathname': '/path', 121 'hash': '#all,%20folks', 122 'path': '/path?that%27s' 123 }, 124 125 'HTTP://X.COM/Y' : { 126 'href': 'http://x.com/Y', 127 'protocol': 'http:', 128 'slashes': true, 129 'host': 'x.com', 130 'hostname': 'x.com', 131 'pathname': '/Y', 132 'path': '/Y' 133 }, 134 135 // an unexpected invalid char in the hostname. 136 'HtTp://x.y.cOm*a/b/c?d=e#f g<h>i' : { 137 'href': 'http://x.y.com/*a/b/c?d=e#f%20g%3Ch%3Ei', 138 'protocol': 'http:', 139 'slashes': true, 140 'host': 'x.y.com', 141 'hostname': 'x.y.com', 142 'pathname': '/*a/b/c', 143 'search': '?d=e', 144 'query': 'd=e', 145 'hash': '#f%20g%3Ch%3Ei', 146 'path': '/*a/b/c?d=e' 147 }, 148 149 // make sure that we don't accidentally lcast the path parts. 150 'HtTp://x.y.cOm*A/b/c?d=e#f g<h>i' : { 151 'href': 'http://x.y.com/*A/b/c?d=e#f%20g%3Ch%3Ei', 152 'protocol': 'http:', 153 'slashes': true, 154 'host': 'x.y.com', 155 'hostname': 'x.y.com', 156 'pathname': '/*A/b/c', 157 'search': '?d=e', 158 'query': 'd=e', 159 'hash': '#f%20g%3Ch%3Ei', 160 'path': '/*A/b/c?d=e' 161 }, 162 163 'http://x...y...#p': { 164 'href': 'http://x...y.../#p', 165 'protocol': 'http:', 166 'slashes': true, 167 'host': 'x...y...', 168 'hostname': 'x...y...', 169 'hash': '#p', 170 'pathname': '/', 171 'path': '/' 172 }, 173 174 'http://x/p/"quoted"': { 175 'href': 'http://x/p/%22quoted%22', 176 'protocol': 'http:', 177 'slashes': true, 178 'host': 'x', 179 'hostname': 'x', 180 'pathname': '/p/%22quoted%22', 181 'path': '/p/%22quoted%22' 182 }, 183 184 '<http://goo.corn/bread> Is a URL!': { 185 'href': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!', 186 'pathname': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!', 187 'path': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!' 188 }, 189 190 'http://www.narwhaljs.org/blog/categories?id=news' : { 191 'href': 'http://www.narwhaljs.org/blog/categories?id=news', 192 'protocol': 'http:', 193 'slashes': true, 194 'host': 'www.narwhaljs.org', 195 'hostname': 'www.narwhaljs.org', 196 'search': '?id=news', 197 'query': 'id=news', 198 'pathname': '/blog/categories', 199 'path': '/blog/categories?id=news' 200 }, 201 202 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=' : { 203 'href': 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=', 204 'protocol': 'http:', 205 'slashes': true, 206 'host': 'mt0.google.com', 207 'hostname': 'mt0.google.com', 208 'pathname': '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=', 209 'path': '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=' 210 }, 211 212 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' : { 213 'href': 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api' + 214 '&x=2&y=2&z=3&s=', 215 'protocol': 'http:', 216 'slashes': true, 217 'host': 'mt0.google.com', 218 'hostname': 'mt0.google.com', 219 'search': '???&hl=en&src=api&x=2&y=2&z=3&s=', 220 'query': '??&hl=en&src=api&x=2&y=2&z=3&s=', 221 'pathname': '/vt/lyrs=m@114', 222 'path': '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' 223 }, 224 225 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': 226 { 227 'href': 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' + 228 '&hl=en&src=api&x=2&y=2&z=3&s=', 229 'protocol': 'http:', 230 'slashes': true, 231 'host': 'mt0.google.com', 232 'auth': 'user:pass', 233 'hostname': 'mt0.google.com', 234 'search': '???&hl=en&src=api&x=2&y=2&z=3&s=', 235 'query': '??&hl=en&src=api&x=2&y=2&z=3&s=', 236 'pathname': '/vt/lyrs=m@114', 237 'path': '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' 238 }, 239 240 'file:///etc/passwd' : { 241 'href': 'file:///etc/passwd', 242 'slashes': true, 243 'protocol': 'file:', 244 'pathname': '/etc/passwd', 245 'hostname': '', 246 'host': '', 247 'path': '/etc/passwd' 248 }, 249 250 'file://localhost/etc/passwd' : { 251 'href': 'file://localhost/etc/passwd', 252 'protocol': 'file:', 253 'slashes': true, 254 'pathname': '/etc/passwd', 255 'hostname': 'localhost', 256 'host': 'localhost', 257 'path': '/etc/passwd' 258 }, 259 260 'file://foo/etc/passwd' : { 261 'href': 'file://foo/etc/passwd', 262 'protocol': 'file:', 263 'slashes': true, 264 'pathname': '/etc/passwd', 265 'hostname': 'foo', 266 'host': 'foo', 267 'path': '/etc/passwd' 268 }, 269 270 'file:///etc/node/' : { 271 'href': 'file:///etc/node/', 272 'slashes': true, 273 'protocol': 'file:', 274 'pathname': '/etc/node/', 275 'hostname': '', 276 'host': '', 277 'path': '/etc/node/' 278 }, 279 280 'file://localhost/etc/node/' : { 281 'href': 'file://localhost/etc/node/', 282 'protocol': 'file:', 283 'slashes': true, 284 'pathname': '/etc/node/', 285 'hostname': 'localhost', 286 'host': 'localhost', 287 'path': '/etc/node/' 288 }, 289 290 'file://foo/etc/node/' : { 291 'href': 'file://foo/etc/node/', 292 'protocol': 'file:', 293 'slashes': true, 294 'pathname': '/etc/node/', 295 'hostname': 'foo', 296 'host': 'foo', 297 'path': '/etc/node/' 298 }, 299 300 'http:/baz/../foo/bar' : { 301 'href': 'http:/baz/../foo/bar', 302 'protocol': 'http:', 303 'pathname': '/baz/../foo/bar', 304 'path': '/baz/../foo/bar' 305 }, 306 307 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag' : { 308 'href': 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag', 309 'protocol': 'http:', 310 'slashes': true, 311 'host': 'example.com:8000', 312 'auth': 'user:pass', 313 'port': '8000', 314 'hostname': 'example.com', 315 'hash': '#frag', 316 'search': '?baz=quux', 317 'query': 'baz=quux', 318 'pathname': '/foo/bar', 319 'path': '/foo/bar?baz=quux' 320 }, 321 322 '//user:pass@example.com:8000/foo/bar?baz=quux#frag' : { 323 'href': '//user:pass@example.com:8000/foo/bar?baz=quux#frag', 324 'slashes': true, 325 'host': 'example.com:8000', 326 'auth': 'user:pass', 327 'port': '8000', 328 'hostname': 'example.com', 329 'hash': '#frag', 330 'search': '?baz=quux', 331 'query': 'baz=quux', 332 'pathname': '/foo/bar', 333 'path': '/foo/bar?baz=quux' 334 }, 335 336 '/foo/bar?baz=quux#frag' : { 337 'href': '/foo/bar?baz=quux#frag', 338 'hash': '#frag', 339 'search': '?baz=quux', 340 'query': 'baz=quux', 341 'pathname': '/foo/bar', 342 'path': '/foo/bar?baz=quux' 343 }, 344 345 'http:/foo/bar?baz=quux#frag' : { 346 'href': 'http:/foo/bar?baz=quux#frag', 347 'protocol': 'http:', 348 'hash': '#frag', 349 'search': '?baz=quux', 350 'query': 'baz=quux', 351 'pathname': '/foo/bar', 352 'path': '/foo/bar?baz=quux' 353 }, 354 355 'mailto:foo@bar.com?subject=hello' : { 356 'href': 'mailto:foo@bar.com?subject=hello', 357 'protocol': 'mailto:', 358 'host': 'bar.com', 359 'auth' : 'foo', 360 'hostname' : 'bar.com', 361 'search': '?subject=hello', 362 'query': 'subject=hello', 363 'path': '?subject=hello' 364 }, 365 366 'javascript:alert(\'hello\');' : { 367 'href': 'javascript:alert(\'hello\');', 368 'protocol': 'javascript:', 369 'pathname': 'alert(\'hello\');', 370 'path': 'alert(\'hello\');' 371 }, 372 373 'xmpp:isaacschlueter@jabber.org' : { 374 'href': 'xmpp:isaacschlueter@jabber.org', 375 'protocol': 'xmpp:', 376 'host': 'jabber.org', 377 'auth': 'isaacschlueter', 378 'hostname': 'jabber.org' 379 }, 380 381 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar' : { 382 'href' : 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar', 383 'protocol' : 'http:', 384 'slashes': true, 385 'host' : '127.0.0.1:8080', 386 'auth' : 'atpass:foo@bar', 387 'hostname' : '127.0.0.1', 388 'port' : '8080', 389 'pathname': '/path', 390 'search' : '?search=foo', 391 'query' : 'search=foo', 392 'hash' : '#bar', 393 'path': '/path?search=foo' 394 }, 395 396 'svn+ssh://foo/bar': { 397 'href': 'svn+ssh://foo/bar', 398 'host': 'foo', 399 'hostname': 'foo', 400 'protocol': 'svn+ssh:', 401 'pathname': '/bar', 402 'path': '/bar', 403 'slashes': true 404 }, 405 406 'dash-test://foo/bar': { 407 'href': 'dash-test://foo/bar', 408 'host': 'foo', 409 'hostname': 'foo', 410 'protocol': 'dash-test:', 411 'pathname': '/bar', 412 'path': '/bar', 413 'slashes': true 414 }, 415 416 'dash-test:foo/bar': { 417 'href': 'dash-test:foo/bar', 418 'host': 'foo', 419 'hostname': 'foo', 420 'protocol': 'dash-test:', 421 'pathname': '/bar', 422 'path': '/bar' 423 }, 424 425 'dot.test://foo/bar': { 426 'href': 'dot.test://foo/bar', 427 'host': 'foo', 428 'hostname': 'foo', 429 'protocol': 'dot.test:', 430 'pathname': '/bar', 431 'path': '/bar', 432 'slashes': true 433 }, 434 435 'dot.test:foo/bar': { 436 'href': 'dot.test:foo/bar', 437 'host': 'foo', 438 'hostname': 'foo', 439 'protocol': 'dot.test:', 440 'pathname': '/bar', 441 'path': '/bar' 442 }, 443 444 // IDNA tests 445 'http://www.日本語.com/' : { 446 'href': 'http://www.xn--wgv71a119e.com/', 447 'protocol': 'http:', 448 'slashes': true, 449 'host': 'www.xn--wgv71a119e.com', 450 'hostname': 'www.xn--wgv71a119e.com', 451 'pathname': '/', 452 'path': '/' 453 }, 454 455 'http://example.Bücher.com/' : { 456 'href': 'http://example.xn--bcher-kva.com/', 457 'protocol': 'http:', 458 'slashes': true, 459 'host': 'example.xn--bcher-kva.com', 460 'hostname': 'example.xn--bcher-kva.com', 461 'pathname': '/', 462 'path': '/' 463 }, 464 465 'http://www.Äffchen.com/' : { 466 'href': 'http://www.xn--ffchen-9ta.com/', 467 'protocol': 'http:', 468 'slashes': true, 469 'host': 'www.xn--ffchen-9ta.com', 470 'hostname': 'www.xn--ffchen-9ta.com', 471 'pathname': '/', 472 'path': '/' 473 }, 474 475 'http://www.Äffchen.cOm*A/b/c?d=e#f g<h>i' : { 476 'href': 'http://www.xn--ffchen-9ta.com/*A/b/c?d=e#f%20g%3Ch%3Ei', 477 'protocol': 'http:', 478 'slashes': true, 479 'host': 'www.xn--ffchen-9ta.com', 480 'hostname': 'www.xn--ffchen-9ta.com', 481 'pathname': '/*A/b/c', 482 'search': '?d=e', 483 'query': 'd=e', 484 'hash': '#f%20g%3Ch%3Ei', 485 'path': '/*A/b/c?d=e' 486 }, 487 488 'http://SÉLIER.COM/' : { 489 'href': 'http://xn--slier-bsa.com/', 490 'protocol': 'http:', 491 'slashes': true, 492 'host': 'xn--slier-bsa.com', 493 'hostname': 'xn--slier-bsa.com', 494 'pathname': '/', 495 'path': '/' 496 }, 497 498 'http://ليهمابتكلموشعربي؟.ي؟/' : { 499 'href': 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/', 500 'protocol': 'http:', 501 'slashes': true, 502 'host': 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f', 503 'hostname': 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f', 504 'pathname': '/', 505 'path': '/' 506 }, 507 508 'http://➡.ws/➡' : { 509 'href': 'http://xn--hgi.ws/➡', 510 'protocol': 'http:', 511 'slashes': true, 512 'host': 'xn--hgi.ws', 513 'hostname': 'xn--hgi.ws', 514 'pathname': '/➡', 515 'path': '/➡' 516 }, 517 518 'http://bucket_name.s3.amazonaws.com/image.jpg': { 519 protocol: 'http:', 520 slashes: true, 521 host: 'bucket_name.s3.amazonaws.com', 522 hostname: 'bucket_name.s3.amazonaws.com', 523 pathname: '/image.jpg', 524 href: 'http://bucket_name.s3.amazonaws.com/image.jpg', 525 'path': '/image.jpg' 526 }, 527 528 'git+http://github.com/joyent/node.git': { 529 protocol: 'git+http:', 530 slashes: true, 531 host: 'github.com', 532 hostname: 'github.com', 533 pathname: '/joyent/node.git', 534 path: '/joyent/node.git', 535 href: 'git+http://github.com/joyent/node.git' 536 }, 537 538 //if local1@domain1 is uses as a relative URL it may 539 //be parse into auth@hostname, but here there is no 540 //way to make it work in url.parse, I add the test to be explicit 541 'local1@domain1': { 542 'pathname': 'local1@domain1', 543 'path': 'local1@domain1', 544 'href': 'local1@domain1' 545 }, 546 547 //While this may seem counter-intuitive, a browser will parse 548 //<a href='www.google.com'> as a path. 549 'www.example.com' : { 550 'href': 'www.example.com', 551 'pathname': 'www.example.com', 552 'path': 'www.example.com' 553 }, 554 555 // ipv6 support 556 '[fe80::1]': { 557 'href': '[fe80::1]', 558 'pathname': '[fe80::1]', 559 'path': '[fe80::1]' 560 }, 561 562 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': { 563 'protocol': 'coap:', 564 'slashes': true, 565 'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]', 566 'hostname': 'fedc:ba98:7654:3210:fedc:ba98:7654:3210', 567 'href': 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/', 568 'pathname': '/', 569 'path': '/' 570 }, 571 572 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': { 573 'protocol': 'coap:', 574 'slashes': true, 575 'host': '[1080:0:0:0:8:800:200c:417a]:61616', 576 'port': '61616', 577 'hostname': '1080:0:0:0:8:800:200c:417a', 578 'href': 'coap://[1080:0:0:0:8:800:200c:417a]:61616/', 579 'pathname': '/', 580 'path': '/' 581 }, 582 583 'http://user:password@[3ffe:2a00:100:7031::1]:8080': { 584 'protocol': 'http:', 585 'slashes': true, 586 'auth': 'user:password', 587 'host': '[3ffe:2a00:100:7031::1]:8080', 588 'port': '8080', 589 'hostname': '3ffe:2a00:100:7031::1', 590 'href': 'http://user:password@[3ffe:2a00:100:7031::1]:8080/', 591 'pathname': '/', 592 'path': '/' 593 }, 594 595 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': { 596 'protocol': 'coap:', 597 'slashes': true, 598 'auth': 'u:p', 599 'host': '[::192.9.5.5]:61616', 600 'port': '61616', 601 'hostname': '::192.9.5.5', 602 'href': 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature', 603 'search': '?n=Temperature', 604 'query': 'n=Temperature', 605 'pathname': '/.well-known/r', 606 'path': '/.well-known/r?n=Temperature' 607 }, 608 609 // empty port 610 'http://example.com:': { 611 'protocol': 'http:', 612 'slashes': true, 613 'host': 'example.com', 614 'hostname': 'example.com', 615 'href': 'http://example.com/', 616 'pathname': '/', 617 'path': '/' 618 }, 619 620 'http://example.com:/a/b.html': { 621 'protocol': 'http:', 622 'slashes': true, 623 'host': 'example.com', 624 'hostname': 'example.com', 625 'href': 'http://example.com/a/b.html', 626 'pathname': '/a/b.html', 627 'path': '/a/b.html' 628 }, 629 630 'http://example.com:?a=b': { 631 'protocol': 'http:', 632 'slashes': true, 633 'host': 'example.com', 634 'hostname': 'example.com', 635 'href': 'http://example.com/?a=b', 636 'search': '?a=b', 637 'query': 'a=b', 638 'pathname': '/', 639 'path': '/?a=b' 640 }, 641 642 'http://example.com:#abc': { 643 'protocol': 'http:', 644 'slashes': true, 645 'host': 'example.com', 646 'hostname': 'example.com', 647 'href': 'http://example.com/#abc', 648 'hash': '#abc', 649 'pathname': '/', 650 'path': '/' 651 }, 652 653 'http://[fe80::1]:/a/b?a=b#abc': { 654 'protocol': 'http:', 655 'slashes': true, 656 'host': '[fe80::1]', 657 'hostname': 'fe80::1', 658 'href': 'http://[fe80::1]/a/b?a=b#abc', 659 'search': '?a=b', 660 'query': 'a=b', 661 'hash': '#abc', 662 'pathname': '/a/b', 663 'path': '/a/b?a=b' 664 }, 665 666 'http://-lovemonsterz.tumblr.com/rss': { 667 'protocol': 'http:', 668 'slashes': true, 669 'host': '-lovemonsterz.tumblr.com', 670 'hostname': '-lovemonsterz.tumblr.com', 671 'href': 'http://-lovemonsterz.tumblr.com/rss', 672 'pathname': '/rss', 673 'path': '/rss', 674 }, 675 676 'http://-lovemonsterz.tumblr.com:80/rss': { 677 'protocol': 'http:', 678 'slashes': true, 679 'port': '80', 680 'host': '-lovemonsterz.tumblr.com:80', 681 'hostname': '-lovemonsterz.tumblr.com', 682 'href': 'http://-lovemonsterz.tumblr.com:80/rss', 683 'pathname': '/rss', 684 'path': '/rss', 685 }, 686 687 'http://user:pass@-lovemonsterz.tumblr.com/rss': { 688 'protocol': 'http:', 689 'slashes': true, 690 'auth': 'user:pass', 691 'host': '-lovemonsterz.tumblr.com', 692 'hostname': '-lovemonsterz.tumblr.com', 693 'href': 'http://user:pass@-lovemonsterz.tumblr.com/rss', 694 'pathname': '/rss', 695 'path': '/rss', 696 }, 697 698 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': { 699 'protocol': 'http:', 700 'slashes': true, 701 'auth': 'user:pass', 702 'port': '80', 703 'host': '-lovemonsterz.tumblr.com:80', 704 'hostname': '-lovemonsterz.tumblr.com', 705 'href': 'http://user:pass@-lovemonsterz.tumblr.com:80/rss', 706 'pathname': '/rss', 707 'path': '/rss', 708 }, 709 710 'http://_jabber._tcp.google.com/test': { 711 'protocol': 'http:', 712 'slashes': true, 713 'host': '_jabber._tcp.google.com', 714 'hostname': '_jabber._tcp.google.com', 715 'href': 'http://_jabber._tcp.google.com/test', 716 'pathname': '/test', 717 'path': '/test', 718 }, 719 720 'http://user:pass@_jabber._tcp.google.com/test': { 721 'protocol': 'http:', 722 'slashes': true, 723 'auth': 'user:pass', 724 'host': '_jabber._tcp.google.com', 725 'hostname': '_jabber._tcp.google.com', 726 'href': 'http://user:pass@_jabber._tcp.google.com/test', 727 'pathname': '/test', 728 'path': '/test', 729 }, 730 731 'http://_jabber._tcp.google.com:80/test': { 732 'protocol': 'http:', 733 'slashes': true, 734 'port': '80', 735 'host': '_jabber._tcp.google.com:80', 736 'hostname': '_jabber._tcp.google.com', 737 'href': 'http://_jabber._tcp.google.com:80/test', 738 'pathname': '/test', 739 'path': '/test', 740 }, 741 742 'http://user:pass@_jabber._tcp.google.com:80/test': { 743 'protocol': 'http:', 744 'slashes': true, 745 'auth': 'user:pass', 746 'port': '80', 747 'host': '_jabber._tcp.google.com:80', 748 'hostname': '_jabber._tcp.google.com', 749 'href': 'http://user:pass@_jabber._tcp.google.com:80/test', 750 'pathname': '/test', 751 'path': '/test', 752 }, 753 754 'http://a@b@c/': { 755 protocol: 'http:', 756 slashes: true, 757 auth: 'a@b', 758 host: 'c', 759 hostname: 'c', 760 href: 'http://a%40b@c/', 761 path: '/', 762 pathname: '/' 763 }, 764 765 'http://a@b?@c': { 766 protocol: 'http:', 767 slashes: true, 768 auth: 'a', 769 host: 'b', 770 hostname: 'b', 771 href: 'http://a@b/?@c', 772 path: '/?@c', 773 pathname: '/', 774 search: '?@c', 775 query: '@c' 776 }, 777 778 'http://a\r" \t\n<\'b:b@c\r\nd/e?f':{ 779 protocol: 'http:', 780 slashes: true, 781 auth: 'a\r" \t\n<\'b:b', 782 host: 'c', 783 port: null, 784 hostname: 'c', 785 hash: null, 786 search: '?f', 787 query: 'f', 788 pathname: '%0D%0Ad/e', 789 path: '%0D%0Ad/e?f', 790 href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f' 791 } 792 793 }; 794 795 for (var u in parseTests) { 796 var actual = url.parse(u), 797 spaced = url.parse(' \t ' + u + '\n\t'); 798 expected = parseTests[u]; 799 800 Object.keys(actual).forEach(function (i) { 801 if (expected[i] === undefined && actual[i] === null) { 802 expected[i] = null; 803 } 804 }); 805 806 assert.deepEqual(actual, expected); 807 assert.deepEqual(spaced, expected); 808 809 var expected = parseTests[u].href, 810 actual = url.format(parseTests[u]); 811 812 assert.equal(actual, expected, 813 'format(' + u + ') == ' + u + '\nactual:' + actual); 814 } 815 816 var parseTestsWithQueryString = { 817 '/foo/bar?baz=quux#frag' : { 818 'href': '/foo/bar?baz=quux#frag', 819 'hash': '#frag', 820 'search': '?baz=quux', 821 'query': { 822 'baz': 'quux' 823 }, 824 'pathname': '/foo/bar', 825 'path': '/foo/bar?baz=quux' 826 }, 827 'http://example.com' : { 828 'href': 'http://example.com/', 829 'protocol': 'http:', 830 'slashes': true, 831 'host': 'example.com', 832 'hostname': 'example.com', 833 'query': {}, 834 'search': '', 835 'pathname': '/', 836 'path': '/' 837 } 838 }; 839 for (var u in parseTestsWithQueryString) { 840 var actual = url.parse(u, true); 841 var expected = parseTestsWithQueryString[u]; 842 for (var i in actual) { 843 if (actual[i] === null && expected[i] === undefined) { 844 expected[i] = null; 845 } 846 } 847 848 assert.deepEqual(actual, expected); 849 } 850 851 // some extra formatting tests, just to verify 852 // that it'll format slightly wonky content to a valid url. 853 var formatTests = { 854 'http://example.com?' : { 855 'href': 'http://example.com/?', 856 'protocol': 'http:', 857 'slashes': true, 858 'host': 'example.com', 859 'hostname': 'example.com', 860 'search': '?', 861 'query': {}, 862 'pathname': '/' 863 }, 864 'http://example.com?foo=bar#frag' : { 865 'href': 'http://example.com/?foo=bar#frag', 866 'protocol': 'http:', 867 'host': 'example.com', 868 'hostname': 'example.com', 869 'hash': '#frag', 870 'search': '?foo=bar', 871 'query': 'foo=bar', 872 'pathname': '/' 873 }, 874 'http://example.com?foo=@bar#frag' : { 875 'href': 'http://example.com/?foo=@bar#frag', 876 'protocol': 'http:', 877 'host': 'example.com', 878 'hostname': 'example.com', 879 'hash': '#frag', 880 'search': '?foo=@bar', 881 'query': 'foo=@bar', 882 'pathname': '/' 883 }, 884 'http://example.com?foo=/bar/#frag' : { 885 'href': 'http://example.com/?foo=/bar/#frag', 886 'protocol': 'http:', 887 'host': 'example.com', 888 'hostname': 'example.com', 889 'hash': '#frag', 890 'search': '?foo=/bar/', 891 'query': 'foo=/bar/', 892 'pathname': '/' 893 }, 894 'http://example.com?foo=?bar/#frag' : { 895 'href': 'http://example.com/?foo=?bar/#frag', 896 'protocol': 'http:', 897 'host': 'example.com', 898 'hostname': 'example.com', 899 'hash': '#frag', 900 'search': '?foo=?bar/', 901 'query': 'foo=?bar/', 902 'pathname': '/' 903 }, 904 'http://example.com#frag=?bar/#frag' : { 905 'href': 'http://example.com/#frag=?bar/#frag', 906 'protocol': 'http:', 907 'host': 'example.com', 908 'hostname': 'example.com', 909 'hash': '#frag=?bar/#frag', 910 'pathname': '/' 911 }, 912 'http://google.com" onload="alert(42)/' : { 913 'href': 'http://google.com/%22%20onload=%22alert(42)/', 914 'protocol': 'http:', 915 'host': 'google.com', 916 'pathname': '/%22%20onload=%22alert(42)/' 917 }, 918 'http://a.com/a/b/c?s#h' : { 919 'href': 'http://a.com/a/b/c?s#h', 920 'protocol': 'http', 921 'host': 'a.com', 922 'pathname': 'a/b/c', 923 'hash': 'h', 924 'search': 's' 925 }, 926 'xmpp:isaacschlueter@jabber.org' : { 927 'href': 'xmpp:isaacschlueter@jabber.org', 928 'protocol': 'xmpp:', 929 'host': 'jabber.org', 930 'auth': 'isaacschlueter', 931 'hostname': 'jabber.org' 932 }, 933 'http://atpass:foo%40bar@127.0.0.1/' : { 934 'href': 'http://atpass:foo%40bar@127.0.0.1/', 935 'auth': 'atpass:foo@bar', 936 'hostname': '127.0.0.1', 937 'protocol': 'http:', 938 'pathname': '/' 939 }, 940 'http://atslash%2F%40:%2F%40@foo/' : { 941 'href': 'http://atslash%2F%40:%2F%40@foo/', 942 'auth': 'atslash/@:/@', 943 'hostname': 'foo', 944 'protocol': 'http:', 945 'pathname': '/' 946 }, 947 'svn+ssh://foo/bar': { 948 'href': 'svn+ssh://foo/bar', 949 'hostname': 'foo', 950 'protocol': 'svn+ssh:', 951 'pathname': '/bar', 952 'slashes': true 953 }, 954 'dash-test://foo/bar': { 955 'href': 'dash-test://foo/bar', 956 'hostname': 'foo', 957 'protocol': 'dash-test:', 958 'pathname': '/bar', 959 'slashes': true 960 }, 961 'dash-test:foo/bar': { 962 'href': 'dash-test:foo/bar', 963 'hostname': 'foo', 964 'protocol': 'dash-test:', 965 'pathname': '/bar' 966 }, 967 'dot.test://foo/bar': { 968 'href': 'dot.test://foo/bar', 969 'hostname': 'foo', 970 'protocol': 'dot.test:', 971 'pathname': '/bar', 972 'slashes': true 973 }, 974 'dot.test:foo/bar': { 975 'href': 'dot.test:foo/bar', 976 'hostname': 'foo', 977 'protocol': 'dot.test:', 978 'pathname': '/bar' 979 }, 980 // ipv6 support 981 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': { 982 'href': 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature', 983 'protocol': 'coap:', 984 'auth': 'u:p', 985 'hostname': '::1', 986 'port': '61616', 987 'pathname': '/.well-known/r', 988 'search': 'n=Temperature' 989 }, 990 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': { 991 'href': 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton', 992 'protocol': 'coap', 993 'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616', 994 'pathname': '/s/stopButton' 995 }, 996 997 // encode context-specific delimiters in path and query, but do not touch 998 // other non-delimiter chars like `%`. 999 // <https://github.com/joyent/node/issues/4082> 1000 1001 // `#`,`?` in path 1002 '/path/to/%%23%3F+=&.txt?foo=theA1#bar' : { 1003 href : '/path/to/%%23%3F+=&.txt?foo=theA1#bar', 1004 pathname: '/path/to/%#?+=&.txt', 1005 query: { 1006 foo: 'theA1' 1007 }, 1008 hash: "#bar" 1009 }, 1010 1011 // `#`,`?` in path + `#` in query 1012 '/path/to/%%23%3F+=&.txt?foo=the%231#bar' : { 1013 href : '/path/to/%%23%3F+=&.txt?foo=the%231#bar', 1014 pathname: '/path/to/%#?+=&.txt', 1015 query: { 1016 foo: 'the#1' 1017 }, 1018 hash: "#bar" 1019 }, 1020 1021 // `?` and `#` in path and search 1022 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': { 1023 href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag', 1024 protocol: 'http:', 1025 hostname: 'ex.com', 1026 hash: '#frag', 1027 search: '?abc=the#1?&foo=bar', 1028 pathname: '/foo?100%m#r', 1029 }, 1030 1031 // `?` and `#` in search only 1032 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': { 1033 href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag', 1034 protocol: 'http:', 1035 hostname: 'ex.com', 1036 hash: '#frag', 1037 search: '?abc=the#1?&foo=bar', 1038 pathname: '/fooA100%mBr', 1039 } 1040 }; 1041 for (var u in formatTests) { 1042 var expect = formatTests[u].href; 1043 delete formatTests[u].href; 1044 var actual = url.format(u); 1045 var actualObj = url.format(formatTests[u]); 1046 assert.equal(actual, expect, 1047 'wonky format(' + u + ') == ' + expect + 1048 '\nactual:' + actual); 1049 assert.equal(actualObj, expect, 1050 'wonky format(' + JSON.stringify(formatTests[u]) + 1051 ') == ' + expect + 1052 '\nactual: ' + actualObj); 1053 } 1054 1055 /* 1056 [from, path, expected] 1057 */ 1058 var relativeTests = [ 1059 ['/foo/bar/baz', 'quux', '/foo/bar/quux'], 1060 ['/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'], 1061 ['/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'], 1062 ['/foo/bar/baz', '../quux/baz', '/foo/quux/baz'], 1063 ['/foo/bar/baz', '/bar', '/bar'], 1064 ['/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'], 1065 ['/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'], 1066 ['/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'], 1067 ['/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'], 1068 ['foo/bar', '../../../baz', '../../baz'], 1069 ['foo/bar/', '../../../baz', '../baz'], 1070 ['http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'], 1071 ['http://example.com/b//c//d;p?q#blarg', 1072 'https:/p/a/t/h?s#hash2', 1073 'https://p/a/t/h?s#hash2'], 1074 ['http://example.com/b//c//d;p?q#blarg', 1075 'https://u:p@h.com/p/a/t/h?s#hash2', 1076 'https://u:p@h.com/p/a/t/h?s#hash2'], 1077 ['http://example.com/b//c//d;p?q#blarg', 1078 'https:/a/b/c/d', 1079 'https://a/b/c/d'], 1080 ['http://example.com/b//c//d;p?q#blarg', 1081 'http:#hash2', 1082 'http://example.com/b//c//d;p?q#hash2'], 1083 ['http://example.com/b//c//d;p?q#blarg', 1084 'http:/p/a/t/h?s#hash2', 1085 'http://example.com/p/a/t/h?s#hash2'], 1086 ['http://example.com/b//c//d;p?q#blarg', 1087 'http://u:p@h.com/p/a/t/h?s#hash2', 1088 'http://u:p@h.com/p/a/t/h?s#hash2'], 1089 ['http://example.com/b//c//d;p?q#blarg', 1090 'http:/a/b/c/d', 1091 'http://example.com/a/b/c/d'], 1092 ['/foo/bar/baz', '/../etc/passwd', '/etc/passwd'] 1093 ]; 1094 relativeTests.forEach(function(relativeTest) { 1095 var a = url.resolve(relativeTest[0], relativeTest[1]), 1096 e = relativeTest[2]; 1097 assert.equal(a, e, 1098 'resolve(' + [relativeTest[0], relativeTest[1]] + ') == ' + e + 1099 '\n actual=' + a); 1100 }); 1101 1102 1103 // https://github.com/joyent/node/issues/568 1104 [ 1105 undefined, 1106 null, 1107 true, 1108 false, 1109 0.0, 1110 0, 1111 [], 1112 {} 1113 ].forEach(function(val) { 1114 assert.throws(function() { url.parse(val); }, TypeError); 1115 }); 1116 1117 1118 // 1119 // Tests below taken from Chiron 1120 // http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js 1121 // 1122 // Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal> 1123 // used with permission under MIT License 1124 // 1125 // Changes marked with @isaacs 1126 1127 var bases = [ 1128 'http://a/b/c/d;p?q', 1129 'http://a/b/c/d;p?q=1/2', 1130 'http://a/b/c/d;p=1/2?q', 1131 'fred:///s//a/b/c', 1132 'http:///s//a/b/c' 1133 ]; 1134 1135 //[to, from, result] 1136 var relativeTests2 = [ 1137 // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html 1138 ['../c', 'foo:a/b', 'foo:c'], 1139 ['foo:.', 'foo:a', 'foo:'], 1140 ['/foo/../../../bar', 'zz:abc', 'zz:/bar'], 1141 ['/foo/../bar', 'zz:abc', 'zz:/bar'], 1142 // @isaacs Disagree. Not how web browsers resolve this. 1143 ['foo/../../../bar', 'zz:abc', 'zz:bar'], 1144 // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added 1145 ['foo/../bar', 'zz:abc', 'zz:bar'], 1146 ['zz:.', 'zz:abc', 'zz:'], 1147 ['/.', bases[0], 'http://a/'], 1148 ['/.foo', bases[0], 'http://a/.foo'], 1149 ['.foo', bases[0], 'http://a/b/c/.foo'], 1150 1151 // http://gbiv.com/protocols/uri/test/rel_examples1.html 1152 // examples from RFC 2396 1153 ['g:h', bases[0], 'g:h'], 1154 ['g', bases[0], 'http://a/b/c/g'], 1155 ['./g', bases[0], 'http://a/b/c/g'], 1156 ['g/', bases[0], 'http://a/b/c/g/'], 1157 ['/g', bases[0], 'http://a/g'], 1158 ['//g', bases[0], 'http://g/'], 1159 // changed with RFC 2396bis 1160 //('?y', bases[0], 'http://a/b/c/d;p?y'], 1161 ['?y', bases[0], 'http://a/b/c/d;p?y'], 1162 ['g?y', bases[0], 'http://a/b/c/g?y'], 1163 // changed with RFC 2396bis 1164 //('#s', bases[0], CURRENT_DOC_URI + '#s'], 1165 ['#s', bases[0], 'http://a/b/c/d;p?q#s'], 1166 ['g#s', bases[0], 'http://a/b/c/g#s'], 1167 ['g?y#s', bases[0], 'http://a/b/c/g?y#s'], 1168 [';x', bases[0], 'http://a/b/c/;x'], 1169 ['g;x', bases[0], 'http://a/b/c/g;x'], 1170 ['g;x?y#s', bases[0], 'http://a/b/c/g;x?y#s'], 1171 // changed with RFC 2396bis 1172 //('', bases[0], CURRENT_DOC_URI], 1173 ['', bases[0], 'http://a/b/c/d;p?q'], 1174 ['.', bases[0], 'http://a/b/c/'], 1175 ['./', bases[0], 'http://a/b/c/'], 1176 ['..', bases[0], 'http://a/b/'], 1177 ['../', bases[0], 'http://a/b/'], 1178 ['../g', bases[0], 'http://a/b/g'], 1179 ['../..', bases[0], 'http://a/'], 1180 ['../../', bases[0], 'http://a/'], 1181 ['../../g', bases[0], 'http://a/g'], 1182 ['../../../g', bases[0], ('http://a/../g', 'http://a/g')], 1183 ['../../../../g', bases[0], ('http://a/../../g', 'http://a/g')], 1184 // changed with RFC 2396bis 1185 //('/./g', bases[0], 'http://a/./g'], 1186 ['/./g', bases[0], 'http://a/g'], 1187 // changed with RFC 2396bis 1188 //('/../g', bases[0], 'http://a/../g'], 1189 ['/../g', bases[0], 'http://a/g'], 1190 ['g.', bases[0], 'http://a/b/c/g.'], 1191 ['.g', bases[0], 'http://a/b/c/.g'], 1192 ['g..', bases[0], 'http://a/b/c/g..'], 1193 ['..g', bases[0], 'http://a/b/c/..g'], 1194 ['./../g', bases[0], 'http://a/b/g'], 1195 ['./g/.', bases[0], 'http://a/b/c/g/'], 1196 ['g/./h', bases[0], 'http://a/b/c/g/h'], 1197 ['g/../h', bases[0], 'http://a/b/c/h'], 1198 ['g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'], 1199 ['g;x=1/../y', bases[0], 'http://a/b/c/y'], 1200 ['g?y/./x', bases[0], 'http://a/b/c/g?y/./x'], 1201 ['g?y/../x', bases[0], 'http://a/b/c/g?y/../x'], 1202 ['g#s/./x', bases[0], 'http://a/b/c/g#s/./x'], 1203 ['g#s/../x', bases[0], 'http://a/b/c/g#s/../x'], 1204 ['http:g', bases[0], ('http:g', 'http://a/b/c/g')], 1205 ['http:', bases[0], ('http:', bases[0])], 1206 // not sure where this one originated 1207 ['/a/b/c/./../../g', bases[0], 'http://a/a/g'], 1208 1209 // http://gbiv.com/protocols/uri/test/rel_examples2.html 1210 // slashes in base URI's query args 1211 ['g', bases[1], 'http://a/b/c/g'], 1212 ['./g', bases[1], 'http://a/b/c/g'], 1213 ['g/', bases[1], 'http://a/b/c/g/'], 1214 ['/g', bases[1], 'http://a/g'], 1215 ['//g', bases[1], 'http://g/'], 1216 // changed in RFC 2396bis 1217 //('?y', bases[1], 'http://a/b/c/?y'], 1218 ['?y', bases[1], 'http://a/b/c/d;p?y'], 1219 ['g?y', bases[1], 'http://a/b/c/g?y'], 1220 ['g?y/./x', bases[1], 'http://a/b/c/g?y/./x'], 1221 ['g?y/../x', bases[1], 'http://a/b/c/g?y/../x'], 1222 ['g#s', bases[1], 'http://a/b/c/g#s'], 1223 ['g#s/./x', bases[1], 'http://a/b/c/g#s/./x'], 1224 ['g#s/../x', bases[1], 'http://a/b/c/g#s/../x'], 1225 ['./', bases[1], 'http://a/b/c/'], 1226 ['../', bases[1], 'http://a/b/'], 1227 ['../g', bases[1], 'http://a/b/g'], 1228 ['../../', bases[1], 'http://a/'], 1229 ['../../g', bases[1], 'http://a/g'], 1230 1231 // http://gbiv.com/protocols/uri/test/rel_examples3.html 1232 // slashes in path params 1233 // all of these changed in RFC 2396bis 1234 ['g', bases[2], 'http://a/b/c/d;p=1/g'], 1235 ['./g', bases[2], 'http://a/b/c/d;p=1/g'], 1236 ['g/', bases[2], 'http://a/b/c/d;p=1/g/'], 1237 ['g?y', bases[2], 'http://a/b/c/d;p=1/g?y'], 1238 [';x', bases[2], 'http://a/b/c/d;p=1/;x'], 1239 ['g;x', bases[2], 'http://a/b/c/d;p=1/g;x'], 1240 ['g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'], 1241 ['g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'], 1242 ['./', bases[2], 'http://a/b/c/d;p=1/'], 1243 ['../', bases[2], 'http://a/b/c/'], 1244 ['../g', bases[2], 'http://a/b/c/g'], 1245 ['../../', bases[2], 'http://a/b/'], 1246 ['../../g', bases[2], 'http://a/b/g'], 1247 1248 // http://gbiv.com/protocols/uri/test/rel_examples4.html 1249 // double and triple slash, unknown scheme 1250 ['g:h', bases[3], 'g:h'], 1251 ['g', bases[3], 'fred:///s//a/b/g'], 1252 ['./g', bases[3], 'fred:///s//a/b/g'], 1253 ['g/', bases[3], 'fred:///s//a/b/g/'], 1254 ['/g', bases[3], 'fred:///g'], // may change to fred:///s//a/g 1255 ['//g', bases[3], 'fred://g'], // may change to fred:///s//g 1256 ['//g/x', bases[3], 'fred://g/x'], // may change to fred:///s//g/x 1257 ['///g', bases[3], 'fred:///g'], 1258 ['./', bases[3], 'fred:///s//a/b/'], 1259 ['../', bases[3], 'fred:///s//a/'], 1260 ['../g', bases[3], 'fred:///s//a/g'], 1261 1262 ['../../', bases[3], 'fred:///s//'], 1263 ['../../g', bases[3], 'fred:///s//g'], 1264 ['../../../g', bases[3], 'fred:///s/g'], 1265 // may change to fred:///s//a/../../../g 1266 ['../../../../g', bases[3], 'fred:///g'], 1267 1268 // http://gbiv.com/protocols/uri/test/rel_examples5.html 1269 // double and triple slash, well-known scheme 1270 ['g:h', bases[4], 'g:h'], 1271 ['g', bases[4], 'http:///s//a/b/g'], 1272 ['./g', bases[4], 'http:///s//a/b/g'], 1273 ['g/', bases[4], 'http:///s//a/b/g/'], 1274 ['/g', bases[4], 'http:///g'], // may change to http:///s//a/g 1275 ['//g', bases[4], 'http://g/'], // may change to http:///s//g 1276 ['//g/x', bases[4], 'http://g/x'], // may change to http:///s//g/x 1277 ['///g', bases[4], 'http:///g'], 1278 ['./', bases[4], 'http:///s//a/b/'], 1279 ['../', bases[4], 'http:///s//a/'], 1280 ['../g', bases[4], 'http:///s//a/g'], 1281 ['../../', bases[4], 'http:///s//'], 1282 ['../../g', bases[4], 'http:///s//g'], 1283 // may change to http:///s//a/../../g 1284 ['../../../g', bases[4], 'http:///s/g'], 1285 // may change to http:///s//a/../../../g 1286 ['../../../../g', bases[4], 'http:///g'], 1287 1288 // from Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py 1289 ['bar:abc', 'foo:xyz', 'bar:abc'], 1290 ['../abc', 'http://example/x/y/z', 'http://example/x/abc'], 1291 ['http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'], 1292 ['../r', 'http://ex/x/y/z', 'http://ex/x/r'], 1293 ['q/r', 'http://ex/x/y', 'http://ex/x/q/r'], 1294 ['q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'], 1295 ['q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'], 1296 ['ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'], 1297 ['', 'http://ex/x/y', 'http://ex/x/y'], 1298 ['', 'http://ex/x/y/', 'http://ex/x/y/'], 1299 ['', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'], 1300 ['z/', 'http://ex/x/y/', 'http://ex/x/y/z/'], 1301 ['#Animal', 1302 'file:/swap/test/animal.rdf', 1303 'file:/swap/test/animal.rdf#Animal'], 1304 ['../abc', 'file:/e/x/y/z', 'file:/e/x/abc'], 1305 ['/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'], 1306 ['../r', 'file:/ex/x/y/z', 'file:/ex/x/r'], 1307 ['/r', 'file:/ex/x/y/z', 'file:/r'], 1308 ['q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'], 1309 ['q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'], 1310 ['q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'], 1311 ['q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'], 1312 ['ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'], 1313 ['', 'file:/ex/x/y', 'file:/ex/x/y'], 1314 ['', 'file:/ex/x/y/', 'file:/ex/x/y/'], 1315 ['', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'], 1316 ['z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'], 1317 ['file://meetings.example.com/cal#m1', 1318 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3', 1319 'file://meetings.example.com/cal#m1'], 1320 ['file://meetings.example.com/cal#m1', 1321 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', 1322 'file://meetings.example.com/cal#m1'], 1323 ['./#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'], 1324 ['./#', 'file:/some/dir/foo', 'file:/some/dir/#'], 1325 // Ryan Lee 1326 ['./', 'http://example/x/abc.efg', 'http://example/x/'], 1327 1328 1329 // Graham Klyne's tests 1330 // http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls 1331 // 01-31 are from Connelly's cases 1332 1333 // 32-49 1334 ['./q:r', 'http://ex/x/y', 'http://ex/x/q:r'], 1335 ['./p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'], 1336 ['?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'], 1337 ['y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'], 1338 ['local/qual@domain.org#frag', 1339 'mailto:local', 1340 'mailto:local/qual@domain.org#frag'], 1341 ['more/qual2@domain2.org#frag', 1342 'mailto:local/qual1@domain1.org', 1343 'mailto:local/more/qual2@domain2.org#frag'], 1344 ['y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'], 1345 ['/x/y?q', 'http://ex?p', 'http://ex/x/y?q'], 1346 ['c/d', 'foo:a/b', 'foo:a/c/d'], 1347 ['/c/d', 'foo:a/b', 'foo:/c/d'], 1348 ['', 'foo:a/b?c#d', 'foo:a/b?c'], 1349 ['b/c', 'foo:a', 'foo:b/c'], 1350 ['../b/c', 'foo:/a/y/z', 'foo:/a/b/c'], 1351 ['./b/c', 'foo:a', 'foo:b/c'], 1352 ['/./b/c', 'foo:a', 'foo:/b/c'], 1353 ['../../d', 'foo://a//b/c', 'foo://a/d'], 1354 ['.', 'foo:a', 'foo:'], 1355 ['..', 'foo:a', 'foo:'], 1356 1357 // 50-57[cf. TimBL comments -- 1358 // http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html, 1359 // http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html) 1360 ['abc', 'http://example/x/y%2Fz', 'http://example/x/abc'], 1361 ['../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'], 1362 ['../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'], 1363 ['abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'], 1364 ['q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'], 1365 ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'], 1366 ['/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'], 1367 ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'], 1368 1369 // 70-77 1370 ['local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'], 1371 ['local2@domain2?query2', 1372 'mailto:local1@domain1', 1373 'mailto:local2@domain2?query2'], 1374 ['local2@domain2?query2', 1375 'mailto:local1@domain1?query1', 1376 'mailto:local2@domain2?query2'], 1377 ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'], 1378 ['local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'], 1379 ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'], 1380 ['http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'], 1381 ['http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'], 1382 1383 // 82-88 1384 // @isaacs Disagree. Not how browsers do it. 1385 // ['http:this', 'http://example.org/base/uri', 'http:this'], 1386 // @isaacs Added 1387 ['http:this', 'http://example.org/base/uri', 'http://example.org/base/this'], 1388 ['http:this', 'http:base', 'http:this'], 1389 ['.//g', 'f:/a', 'f://g'], 1390 ['b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'], 1391 ['m2@example.ord/c2@example.org', 1392 'mid:m@example.ord/c@example.org', 1393 'mid:m@example.ord/m2@example.ord/c2@example.org'], 1394 ['mini1.xml', 1395 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/', 1396 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'], 1397 ['../b/c', 'foo:a/y/z', 'foo:a/b/c'], 1398 1399 //changeing auth 1400 ['http://diff:auth@www.example.com', 1401 'http://asdf:qwer@www.example.com', 1402 'http://diff:auth@www.example.com/'] 1403 ]; 1404 relativeTests2.forEach(function(relativeTest) { 1405 var a = url.resolve(relativeTest[1], relativeTest[0]), 1406 e = relativeTest[2]; 1407 assert.equal(a, e, 1408 'resolve(' + [relativeTest[1], relativeTest[0]] + ') == ' + e + 1409 '\n actual=' + a); 1410 }); 1411 1412 //if format and parse are inverse operations then 1413 //resolveObject(parse(x), y) == parse(resolve(x, y)) 1414 1415 //host and hostname are special, in this case a '' value is important 1416 var emptyIsImportant = {'host': true, 'hostname': ''}; 1417 1418 //format: [from, path, expected] 1419 relativeTests.forEach(function(relativeTest) { 1420 var actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]), 1421 expected = url.parse(relativeTest[2]); 1422 1423 1424 assert.deepEqual(actual, expected); 1425 1426 expected = relativeTest[2]; 1427 actual = url.format(actual); 1428 1429 assert.equal(actual, expected, 1430 'format(' + actual + ') == ' + expected + '\nactual:' + actual); 1431 }); 1432 1433 //format: [to, from, result] 1434 // the test: ['.//g', 'f:/a', 'f://g'] is a fundimental problem 1435 // url.parse('f:/a') does not have a host 1436 // url.resolve('f:/a', './/g') does not have a host becuase you have moved 1437 // down to the g directory. i.e. f: //g, however when this url is parsed 1438 // f:// will indicate that the host is g which is not the case. 1439 // it is unclear to me how to keep this information from being lost 1440 // it may be that a pathname of ////g should colapse to /g but this seems 1441 // to be a lot of work for an edge case. Right now I remove the test 1442 if (relativeTests2[181][0] === './/g' && 1443 relativeTests2[181][1] === 'f:/a' && 1444 relativeTests2[181][2] === 'f://g') { 1445 relativeTests2.splice(181, 1); 1446 } 1447 relativeTests2.forEach(function(relativeTest) { 1448 var actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]), 1449 expected = url.parse(relativeTest[2]); 1450 1451 assert.deepEqual(actual, expected); 1452 1453 var expected = relativeTest[2], 1454 actual = url.format(actual); 1455 1456 assert.equal(actual, expected, 1457 'format(' + relativeTest[1] + ') == ' + expected + 1458 '\nactual:' + actual); 1459 }); 1460 1461 });