1'use strict'; 2const common = require('../common'); 3 4if (!common.hasIntl) 5 common.skip('missing Intl'); 6 7const assert = require('assert'); 8const inspect = require('util').inspect; 9 10const url = require('url'); 11 12// URLs to parse, and expected data 13// { url : parsed } 14const parseTests = { 15 '//some_path': { 16 href: '//some_path', 17 pathname: '//some_path', 18 path: '//some_path' 19 }, 20 21 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h': { 22 protocol: 'http:', 23 slashes: true, 24 host: 'evil-phisher', 25 hostname: 'evil-phisher', 26 pathname: '/foo.html', 27 path: '/foo.html', 28 hash: '#h%5Ca%5Cs%5Ch', 29 href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch' 30 }, 31 32 'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': { 33 protocol: 'http:', 34 slashes: true, 35 host: 'evil-phisher', 36 hostname: 'evil-phisher', 37 pathname: '/foo.html', 38 search: '?json=%22%5C%22foo%5C%22%22', 39 query: 'json=%22%5C%22foo%5C%22%22', 40 path: '/foo.html?json=%22%5C%22foo%5C%22%22', 41 hash: '#h%5Ca%5Cs%5Ch', 42 href: 'http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch' 43 }, 44 45 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg': { 46 protocol: 'http:', 47 slashes: true, 48 host: 'evil-phisher', 49 hostname: 'evil-phisher', 50 pathname: '/foo.html', 51 path: '/foo.html', 52 hash: '#h%5Ca%5Cs%5Ch?blarg', 53 href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg' 54 }, 55 56 57 'http:\\\\evil-phisher\\foo.html': { 58 protocol: 'http:', 59 slashes: true, 60 host: 'evil-phisher', 61 hostname: 'evil-phisher', 62 pathname: '/foo.html', 63 path: '/foo.html', 64 href: 'http://evil-phisher/foo.html' 65 }, 66 67 'HTTP://www.example.com/': { 68 href: 'http://www.example.com/', 69 protocol: 'http:', 70 slashes: true, 71 host: 'www.example.com', 72 hostname: 'www.example.com', 73 pathname: '/', 74 path: '/' 75 }, 76 77 'HTTP://www.example.com': { 78 href: 'http://www.example.com/', 79 protocol: 'http:', 80 slashes: true, 81 host: 'www.example.com', 82 hostname: 'www.example.com', 83 pathname: '/', 84 path: '/' 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://user:pw@www.ExAmPlE.com/': { 98 href: 'http://user:pw@www.example.com/', 99 protocol: 'http:', 100 slashes: true, 101 auth: 'user:pw', 102 host: 'www.example.com', 103 hostname: 'www.example.com', 104 pathname: '/', 105 path: '/' 106 }, 107 108 'http://USER:PW@www.ExAmPlE.com/': { 109 href: 'http://USER:PW@www.example.com/', 110 protocol: 'http:', 111 slashes: true, 112 auth: 'USER:PW', 113 host: 'www.example.com', 114 hostname: 'www.example.com', 115 pathname: '/', 116 path: '/' 117 }, 118 119 'http://user@www.example.com/': { 120 href: 'http://user@www.example.com/', 121 protocol: 'http:', 122 slashes: true, 123 auth: 'user', 124 host: 'www.example.com', 125 hostname: 'www.example.com', 126 pathname: '/', 127 path: '/' 128 }, 129 130 'http://user%3Apw@www.example.com/': { 131 href: 'http://user:pw@www.example.com/', 132 protocol: 'http:', 133 slashes: true, 134 auth: 'user:pw', 135 host: 'www.example.com', 136 hostname: 'www.example.com', 137 pathname: '/', 138 path: '/' 139 }, 140 141 'http://x.com/path?that\'s#all, folks': { 142 href: 'http://x.com/path?that%27s#all,%20folks', 143 protocol: 'http:', 144 slashes: true, 145 host: 'x.com', 146 hostname: 'x.com', 147 search: '?that%27s', 148 query: 'that%27s', 149 pathname: '/path', 150 hash: '#all,%20folks', 151 path: '/path?that%27s' 152 }, 153 154 'HTTP://X.COM/Y': { 155 href: 'http://x.com/Y', 156 protocol: 'http:', 157 slashes: true, 158 host: 'x.com', 159 hostname: 'x.com', 160 pathname: '/Y', 161 path: '/Y' 162 }, 163 164 // Whitespace in the front 165 ' http://www.example.com/': { 166 href: 'http://www.example.com/', 167 protocol: 'http:', 168 slashes: true, 169 host: 'www.example.com', 170 hostname: 'www.example.com', 171 pathname: '/', 172 path: '/' 173 }, 174 175 // + not an invalid host character 176 // per https://url.spec.whatwg.org/#host-parsing 177 'http://x.y.com+a/b/c': { 178 href: 'http://x.y.com+a/b/c', 179 protocol: 'http:', 180 slashes: true, 181 host: 'x.y.com+a', 182 hostname: 'x.y.com+a', 183 pathname: '/b/c', 184 path: '/b/c' 185 }, 186 187 // An unexpected invalid char in the hostname. 188 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i': { 189 href: 'http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei', 190 protocol: 'http:', 191 slashes: true, 192 host: 'x.y.com', 193 hostname: 'x.y.com', 194 pathname: ';a/b/c', 195 search: '?d=e', 196 query: 'd=e', 197 hash: '#f%20g%3Ch%3Ei', 198 path: ';a/b/c?d=e' 199 }, 200 201 // Make sure that we don't accidentally lcast the path parts. 202 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i': { 203 href: 'http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei', 204 protocol: 'http:', 205 slashes: true, 206 host: 'x.y.com', 207 hostname: 'x.y.com', 208 pathname: ';A/b/c', 209 search: '?d=e', 210 query: 'd=e', 211 hash: '#f%20g%3Ch%3Ei', 212 path: ';A/b/c?d=e' 213 }, 214 215 'http://x...y...#p': { 216 href: 'http://x...y.../#p', 217 protocol: 'http:', 218 slashes: true, 219 host: 'x...y...', 220 hostname: 'x...y...', 221 hash: '#p', 222 pathname: '/', 223 path: '/' 224 }, 225 226 'http://x/p/"quoted"': { 227 href: 'http://x/p/%22quoted%22', 228 protocol: 'http:', 229 slashes: true, 230 host: 'x', 231 hostname: 'x', 232 pathname: '/p/%22quoted%22', 233 path: '/p/%22quoted%22' 234 }, 235 236 '<http://goo.corn/bread> Is a URL!': { 237 href: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!', 238 pathname: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!', 239 path: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!' 240 }, 241 242 'http://www.narwhaljs.org/blog/categories?id=news': { 243 href: 'http://www.narwhaljs.org/blog/categories?id=news', 244 protocol: 'http:', 245 slashes: true, 246 host: 'www.narwhaljs.org', 247 hostname: 'www.narwhaljs.org', 248 search: '?id=news', 249 query: 'id=news', 250 pathname: '/blog/categories', 251 path: '/blog/categories?id=news' 252 }, 253 254 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=': { 255 href: 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=', 256 protocol: 'http:', 257 slashes: true, 258 host: 'mt0.google.com', 259 hostname: 'mt0.google.com', 260 pathname: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=', 261 path: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=' 262 }, 263 264 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': { 265 href: 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api' + 266 '&x=2&y=2&z=3&s=', 267 protocol: 'http:', 268 slashes: true, 269 host: 'mt0.google.com', 270 hostname: 'mt0.google.com', 271 search: '???&hl=en&src=api&x=2&y=2&z=3&s=', 272 query: '??&hl=en&src=api&x=2&y=2&z=3&s=', 273 pathname: '/vt/lyrs=m@114', 274 path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' 275 }, 276 277 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': { 278 href: 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=', 279 protocol: 'http:', 280 slashes: true, 281 host: 'mt0.google.com', 282 auth: 'user:pass', 283 hostname: 'mt0.google.com', 284 search: '???&hl=en&src=api&x=2&y=2&z=3&s=', 285 query: '??&hl=en&src=api&x=2&y=2&z=3&s=', 286 pathname: '/vt/lyrs=m@114', 287 path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' 288 }, 289 290 'file:///etc/passwd': { 291 href: 'file:///etc/passwd', 292 slashes: true, 293 protocol: 'file:', 294 pathname: '/etc/passwd', 295 hostname: '', 296 host: '', 297 path: '/etc/passwd' 298 }, 299 300 'file://localhost/etc/passwd': { 301 href: 'file://localhost/etc/passwd', 302 protocol: 'file:', 303 slashes: true, 304 pathname: '/etc/passwd', 305 hostname: 'localhost', 306 host: 'localhost', 307 path: '/etc/passwd' 308 }, 309 310 'file://foo/etc/passwd': { 311 href: 'file://foo/etc/passwd', 312 protocol: 'file:', 313 slashes: true, 314 pathname: '/etc/passwd', 315 hostname: 'foo', 316 host: 'foo', 317 path: '/etc/passwd' 318 }, 319 320 'file:///etc/node/': { 321 href: 'file:///etc/node/', 322 slashes: true, 323 protocol: 'file:', 324 pathname: '/etc/node/', 325 hostname: '', 326 host: '', 327 path: '/etc/node/' 328 }, 329 330 'file://localhost/etc/node/': { 331 href: 'file://localhost/etc/node/', 332 protocol: 'file:', 333 slashes: true, 334 pathname: '/etc/node/', 335 hostname: 'localhost', 336 host: 'localhost', 337 path: '/etc/node/' 338 }, 339 340 'file://foo/etc/node/': { 341 href: 'file://foo/etc/node/', 342 protocol: 'file:', 343 slashes: true, 344 pathname: '/etc/node/', 345 hostname: 'foo', 346 host: 'foo', 347 path: '/etc/node/' 348 }, 349 350 'http:/baz/../foo/bar': { 351 href: 'http:/baz/../foo/bar', 352 protocol: 'http:', 353 pathname: '/baz/../foo/bar', 354 path: '/baz/../foo/bar' 355 }, 356 357 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag': { 358 href: 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag', 359 protocol: 'http:', 360 slashes: true, 361 host: 'example.com:8000', 362 auth: 'user:pass', 363 port: '8000', 364 hostname: 'example.com', 365 hash: '#frag', 366 search: '?baz=quux', 367 query: 'baz=quux', 368 pathname: '/foo/bar', 369 path: '/foo/bar?baz=quux' 370 }, 371 372 '//user:pass@example.com:8000/foo/bar?baz=quux#frag': { 373 href: '//user:pass@example.com:8000/foo/bar?baz=quux#frag', 374 slashes: true, 375 host: 'example.com:8000', 376 auth: 'user:pass', 377 port: '8000', 378 hostname: 'example.com', 379 hash: '#frag', 380 search: '?baz=quux', 381 query: 'baz=quux', 382 pathname: '/foo/bar', 383 path: '/foo/bar?baz=quux' 384 }, 385 386 '/foo/bar?baz=quux#frag': { 387 href: '/foo/bar?baz=quux#frag', 388 hash: '#frag', 389 search: '?baz=quux', 390 query: 'baz=quux', 391 pathname: '/foo/bar', 392 path: '/foo/bar?baz=quux' 393 }, 394 395 'http:/foo/bar?baz=quux#frag': { 396 href: 'http:/foo/bar?baz=quux#frag', 397 protocol: 'http:', 398 hash: '#frag', 399 search: '?baz=quux', 400 query: 'baz=quux', 401 pathname: '/foo/bar', 402 path: '/foo/bar?baz=quux' 403 }, 404 405 'mailto:foo@bar.com?subject=hello': { 406 href: 'mailto:foo@bar.com?subject=hello', 407 protocol: 'mailto:', 408 host: 'bar.com', 409 auth: 'foo', 410 hostname: 'bar.com', 411 search: '?subject=hello', 412 query: 'subject=hello', 413 path: '?subject=hello' 414 }, 415 416 'javascript:alert(\'hello\');': { 417 href: 'javascript:alert(\'hello\');', 418 protocol: 'javascript:', 419 pathname: 'alert(\'hello\');', 420 path: 'alert(\'hello\');' 421 }, 422 423 'xmpp:isaacschlueter@jabber.org': { 424 href: 'xmpp:isaacschlueter@jabber.org', 425 protocol: 'xmpp:', 426 host: 'jabber.org', 427 auth: 'isaacschlueter', 428 hostname: 'jabber.org' 429 }, 430 431 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar': { 432 href: 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar', 433 protocol: 'http:', 434 slashes: true, 435 host: '127.0.0.1:8080', 436 auth: 'atpass:foo@bar', 437 hostname: '127.0.0.1', 438 port: '8080', 439 pathname: '/path', 440 search: '?search=foo', 441 query: 'search=foo', 442 hash: '#bar', 443 path: '/path?search=foo' 444 }, 445 446 'svn+ssh://foo/bar': { 447 href: 'svn+ssh://foo/bar', 448 host: 'foo', 449 hostname: 'foo', 450 protocol: 'svn+ssh:', 451 pathname: '/bar', 452 path: '/bar', 453 slashes: true 454 }, 455 456 'dash-test://foo/bar': { 457 href: 'dash-test://foo/bar', 458 host: 'foo', 459 hostname: 'foo', 460 protocol: 'dash-test:', 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 }, 474 475 'dot.test://foo/bar': { 476 href: 'dot.test://foo/bar', 477 host: 'foo', 478 hostname: 'foo', 479 protocol: 'dot.test:', 480 pathname: '/bar', 481 path: '/bar', 482 slashes: true 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 }, 493 494 // IDNA tests 495 'http://www.日本語.com/': { 496 href: 'http://www.xn--wgv71a119e.com/', 497 protocol: 'http:', 498 slashes: true, 499 host: 'www.xn--wgv71a119e.com', 500 hostname: 'www.xn--wgv71a119e.com', 501 pathname: '/', 502 path: '/' 503 }, 504 505 'http://example.Bücher.com/': { 506 href: 'http://example.xn--bcher-kva.com/', 507 protocol: 'http:', 508 slashes: true, 509 host: 'example.xn--bcher-kva.com', 510 hostname: 'example.xn--bcher-kva.com', 511 pathname: '/', 512 path: '/' 513 }, 514 515 'http://www.Äffchen.com/': { 516 href: 'http://www.xn--ffchen-9ta.com/', 517 protocol: 'http:', 518 slashes: true, 519 host: 'www.xn--ffchen-9ta.com', 520 hostname: 'www.xn--ffchen-9ta.com', 521 pathname: '/', 522 path: '/' 523 }, 524 525 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i': { 526 href: 'http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei', 527 protocol: 'http:', 528 slashes: true, 529 host: 'www.xn--ffchen-9ta.com', 530 hostname: 'www.xn--ffchen-9ta.com', 531 pathname: ';A/b/c', 532 search: '?d=e', 533 query: 'd=e', 534 hash: '#f%20g%3Ch%3Ei', 535 path: ';A/b/c?d=e' 536 }, 537 538 'http://SÉLIER.COM/': { 539 href: 'http://xn--slier-bsa.com/', 540 protocol: 'http:', 541 slashes: true, 542 host: 'xn--slier-bsa.com', 543 hostname: 'xn--slier-bsa.com', 544 pathname: '/', 545 path: '/' 546 }, 547 548 'http://ليهمابتكلموشعربي؟.ي؟/': { 549 href: 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/', 550 protocol: 'http:', 551 slashes: true, 552 host: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f', 553 hostname: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f', 554 pathname: '/', 555 path: '/' 556 }, 557 558 'http://➡.ws/➡': { 559 href: 'http://xn--hgi.ws/➡', 560 protocol: 'http:', 561 slashes: true, 562 host: 'xn--hgi.ws', 563 hostname: 'xn--hgi.ws', 564 pathname: '/➡', 565 path: '/➡' 566 }, 567 568 'http://bucket_name.s3.amazonaws.com/image.jpg': { 569 protocol: 'http:', 570 slashes: true, 571 host: 'bucket_name.s3.amazonaws.com', 572 hostname: 'bucket_name.s3.amazonaws.com', 573 pathname: '/image.jpg', 574 href: 'http://bucket_name.s3.amazonaws.com/image.jpg', 575 path: '/image.jpg' 576 }, 577 578 'git+http://github.com/joyent/node.git': { 579 protocol: 'git+http:', 580 slashes: true, 581 host: 'github.com', 582 hostname: 'github.com', 583 pathname: '/joyent/node.git', 584 path: '/joyent/node.git', 585 href: 'git+http://github.com/joyent/node.git' 586 }, 587 588 // If local1@domain1 is uses as a relative URL it may 589 // be parse into auth@hostname, but here there is no 590 // way to make it work in url.parse, I add the test to be explicit 591 'local1@domain1': { 592 pathname: 'local1@domain1', 593 path: 'local1@domain1', 594 href: 'local1@domain1' 595 }, 596 597 // While this may seem counter-intuitive, a browser will parse 598 // <a href='www.google.com'> as a path. 599 'www.example.com': { 600 href: 'www.example.com', 601 pathname: 'www.example.com', 602 path: 'www.example.com' 603 }, 604 605 // ipv6 support 606 '[fe80::1]': { 607 href: '[fe80::1]', 608 pathname: '[fe80::1]', 609 path: '[fe80::1]' 610 }, 611 612 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': { 613 protocol: 'coap:', 614 slashes: true, 615 host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]', 616 hostname: 'fedc:ba98:7654:3210:fedc:ba98:7654:3210', 617 href: 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/', 618 pathname: '/', 619 path: '/' 620 }, 621 622 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': { 623 protocol: 'coap:', 624 slashes: true, 625 host: '[1080:0:0:0:8:800:200c:417a]:61616', 626 port: '61616', 627 hostname: '1080:0:0:0:8:800:200c:417a', 628 href: 'coap://[1080:0:0:0:8:800:200c:417a]:61616/', 629 pathname: '/', 630 path: '/' 631 }, 632 633 'http://user:password@[3ffe:2a00:100:7031::1]:8080': { 634 protocol: 'http:', 635 slashes: true, 636 auth: 'user:password', 637 host: '[3ffe:2a00:100:7031::1]:8080', 638 port: '8080', 639 hostname: '3ffe:2a00:100:7031::1', 640 href: 'http://user:password@[3ffe:2a00:100:7031::1]:8080/', 641 pathname: '/', 642 path: '/' 643 }, 644 645 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': { 646 protocol: 'coap:', 647 slashes: true, 648 auth: 'u:p', 649 host: '[::192.9.5.5]:61616', 650 port: '61616', 651 hostname: '::192.9.5.5', 652 href: 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature', 653 search: '?n=Temperature', 654 query: 'n=Temperature', 655 pathname: '/.well-known/r', 656 path: '/.well-known/r?n=Temperature' 657 }, 658 659 // empty port 660 'http://example.com:': { 661 protocol: 'http:', 662 slashes: true, 663 host: 'example.com', 664 hostname: 'example.com', 665 href: 'http://example.com/', 666 pathname: '/', 667 path: '/' 668 }, 669 670 'http://example.com:/a/b.html': { 671 protocol: 'http:', 672 slashes: true, 673 host: 'example.com', 674 hostname: 'example.com', 675 href: 'http://example.com/a/b.html', 676 pathname: '/a/b.html', 677 path: '/a/b.html' 678 }, 679 680 'http://example.com:?a=b': { 681 protocol: 'http:', 682 slashes: true, 683 host: 'example.com', 684 hostname: 'example.com', 685 href: 'http://example.com/?a=b', 686 search: '?a=b', 687 query: 'a=b', 688 pathname: '/', 689 path: '/?a=b' 690 }, 691 692 'http://example.com:#abc': { 693 protocol: 'http:', 694 slashes: true, 695 host: 'example.com', 696 hostname: 'example.com', 697 href: 'http://example.com/#abc', 698 hash: '#abc', 699 pathname: '/', 700 path: '/' 701 }, 702 703 'http://[fe80::1]:/a/b?a=b#abc': { 704 protocol: 'http:', 705 slashes: true, 706 host: '[fe80::1]', 707 hostname: 'fe80::1', 708 href: 'http://[fe80::1]/a/b?a=b#abc', 709 search: '?a=b', 710 query: 'a=b', 711 hash: '#abc', 712 pathname: '/a/b', 713 path: '/a/b?a=b' 714 }, 715 716 'http://-lovemonsterz.tumblr.com/rss': { 717 protocol: 'http:', 718 slashes: true, 719 host: '-lovemonsterz.tumblr.com', 720 hostname: '-lovemonsterz.tumblr.com', 721 href: 'http://-lovemonsterz.tumblr.com/rss', 722 pathname: '/rss', 723 path: '/rss', 724 }, 725 726 'http://-lovemonsterz.tumblr.com:80/rss': { 727 protocol: 'http:', 728 slashes: true, 729 port: '80', 730 host: '-lovemonsterz.tumblr.com:80', 731 hostname: '-lovemonsterz.tumblr.com', 732 href: 'http://-lovemonsterz.tumblr.com:80/rss', 733 pathname: '/rss', 734 path: '/rss', 735 }, 736 737 'http://user:pass@-lovemonsterz.tumblr.com/rss': { 738 protocol: 'http:', 739 slashes: true, 740 auth: 'user:pass', 741 host: '-lovemonsterz.tumblr.com', 742 hostname: '-lovemonsterz.tumblr.com', 743 href: 'http://user:pass@-lovemonsterz.tumblr.com/rss', 744 pathname: '/rss', 745 path: '/rss', 746 }, 747 748 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': { 749 protocol: 'http:', 750 slashes: true, 751 auth: 'user:pass', 752 port: '80', 753 host: '-lovemonsterz.tumblr.com:80', 754 hostname: '-lovemonsterz.tumblr.com', 755 href: 'http://user:pass@-lovemonsterz.tumblr.com:80/rss', 756 pathname: '/rss', 757 path: '/rss', 758 }, 759 760 'http://_jabber._tcp.google.com/test': { 761 protocol: 'http:', 762 slashes: true, 763 host: '_jabber._tcp.google.com', 764 hostname: '_jabber._tcp.google.com', 765 href: 'http://_jabber._tcp.google.com/test', 766 pathname: '/test', 767 path: '/test', 768 }, 769 770 'http://user:pass@_jabber._tcp.google.com/test': { 771 protocol: 'http:', 772 slashes: true, 773 auth: 'user:pass', 774 host: '_jabber._tcp.google.com', 775 hostname: '_jabber._tcp.google.com', 776 href: 'http://user:pass@_jabber._tcp.google.com/test', 777 pathname: '/test', 778 path: '/test', 779 }, 780 781 'http://_jabber._tcp.google.com:80/test': { 782 protocol: 'http:', 783 slashes: true, 784 port: '80', 785 host: '_jabber._tcp.google.com:80', 786 hostname: '_jabber._tcp.google.com', 787 href: 'http://_jabber._tcp.google.com:80/test', 788 pathname: '/test', 789 path: '/test', 790 }, 791 792 'http://user:pass@_jabber._tcp.google.com:80/test': { 793 protocol: 'http:', 794 slashes: true, 795 auth: 'user:pass', 796 port: '80', 797 host: '_jabber._tcp.google.com:80', 798 hostname: '_jabber._tcp.google.com', 799 href: 'http://user:pass@_jabber._tcp.google.com:80/test', 800 pathname: '/test', 801 path: '/test', 802 }, 803 804 'http://x:1/\' <>"`/{}|\\^~`/': { 805 protocol: 'http:', 806 slashes: true, 807 host: 'x:1', 808 port: '1', 809 hostname: 'x', 810 pathname: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/', 811 path: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/', 812 href: 'http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/' 813 }, 814 815 'http://a@b@c/': { 816 protocol: 'http:', 817 slashes: true, 818 auth: 'a@b', 819 host: 'c', 820 hostname: 'c', 821 href: 'http://a%40b@c/', 822 path: '/', 823 pathname: '/' 824 }, 825 826 'http://a@b?@c': { 827 protocol: 'http:', 828 slashes: true, 829 auth: 'a', 830 host: 'b', 831 hostname: 'b', 832 href: 'http://a@b/?@c', 833 path: '/?@c', 834 pathname: '/', 835 search: '?@c', 836 query: '@c' 837 }, 838 839 'http://a.b/\tbc\ndr\ref g"hq\'j<kl>?mn\\op^q=r`99{st|uv}wz': { 840 protocol: 'http:', 841 slashes: true, 842 host: 'a.b', 843 port: null, 844 hostname: 'a.b', 845 hash: null, 846 pathname: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E', 847 path: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz', 848 search: '?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz', 849 query: 'mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz', 850 href: 'http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz' 851 }, 852 853 'http://a\r" \t\n<\'b:b@c\r\nd/e?f': { 854 protocol: 'http:', 855 slashes: true, 856 auth: 'a" <\'b:b', 857 host: 'cd', 858 port: null, 859 hostname: 'cd', 860 hash: null, 861 search: '?f', 862 query: 'f', 863 pathname: '/e', 864 path: '/e?f', 865 href: 'http://a%22%20%3C\'b:b@cd/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 'https://*': { 885 protocol: 'https:', 886 slashes: true, 887 auth: null, 888 host: '*', 889 port: null, 890 hostname: '*', 891 hash: null, 892 search: null, 893 query: null, 894 pathname: '/', 895 path: '/', 896 href: 'https://*/' 897 }, 898 899 // The following two URLs are the same, but they differ for a capital A. 900 // Verify that the protocol is checked in a case-insensitive manner. 901 'javascript:alert(1);a=\x27@white-listed.com\x27': { 902 protocol: 'javascript:', 903 slashes: null, 904 auth: null, 905 host: null, 906 port: null, 907 hostname: null, 908 hash: null, 909 search: null, 910 query: null, 911 pathname: "alert(1);a='@white-listed.com'", 912 path: "alert(1);a='@white-listed.com'", 913 href: "javascript:alert(1);a='@white-listed.com'" 914 }, 915 916 'javAscript:alert(1);a=\x27@white-listed.com\x27': { 917 protocol: 'javascript:', 918 slashes: null, 919 auth: null, 920 host: null, 921 port: null, 922 hostname: null, 923 hash: null, 924 search: null, 925 query: null, 926 pathname: "alert(1);a='@white-listed.com'", 927 path: "alert(1);a='@white-listed.com'", 928 href: "javascript:alert(1);a='@white-listed.com'" 929 }, 930 931 'ws://www.example.com': { 932 protocol: 'ws:', 933 slashes: true, 934 hostname: 'www.example.com', 935 host: 'www.example.com', 936 pathname: '/', 937 path: '/', 938 href: 'ws://www.example.com/' 939 }, 940 941 'wss://www.example.com': { 942 protocol: 'wss:', 943 slashes: true, 944 hostname: 'www.example.com', 945 host: 'www.example.com', 946 pathname: '/', 947 path: '/', 948 href: 'wss://www.example.com/' 949 }, 950 951 '//fhqwhgads@example.com/everybody-to-the-limit': { 952 protocol: null, 953 slashes: true, 954 auth: 'fhqwhgads', 955 host: 'example.com', 956 port: null, 957 hostname: 'example.com', 958 hash: null, 959 search: null, 960 query: null, 961 pathname: '/everybody-to-the-limit', 962 path: '/everybody-to-the-limit', 963 href: '//fhqwhgads@example.com/everybody-to-the-limit' 964 }, 965 966 '//fhqwhgads@example.com/everybody#to-the-limit': { 967 protocol: null, 968 slashes: true, 969 auth: 'fhqwhgads', 970 host: 'example.com', 971 port: null, 972 hostname: 'example.com', 973 hash: '#to-the-limit', 974 search: null, 975 query: null, 976 pathname: '/everybody', 977 path: '/everybody', 978 href: '//fhqwhgads@example.com/everybody#to-the-limit' 979 }, 980 981 '\bhttp://example.com/\b': { 982 protocol: 'http:', 983 slashes: true, 984 auth: null, 985 host: 'example.com', 986 port: null, 987 hostname: 'example.com', 988 hash: null, 989 search: null, 990 query: null, 991 pathname: '/', 992 path: '/', 993 href: 'http://example.com/' 994 }, 995 996 'https://evil.com$.example.com': { 997 protocol: 'https:', 998 slashes: true, 999 auth: null, 1000 host: 'evil.com$.example.com', 1001 port: null, 1002 hostname: 'evil.com$.example.com', 1003 hash: null, 1004 search: null, 1005 query: null, 1006 pathname: '/', 1007 path: '/', 1008 href: 'https://evil.com$.example.com/' 1009 }, 1010 1011 // Validate the output of hostname with commas. 1012 'x://0.0,1.1/': { 1013 protocol: 'x:', 1014 slashes: true, 1015 auth: null, 1016 host: '0.0,1.1', 1017 port: null, 1018 hostname: '0.0,1.1', 1019 hash: null, 1020 search: null, 1021 query: null, 1022 pathname: '/', 1023 path: '/', 1024 href: 'x://0.0,1.1/' 1025 } 1026}; 1027 1028for (const u in parseTests) { 1029 let actual = url.parse(u); 1030 const spaced = url.parse(` \t ${u}\n\t`); 1031 let expected = Object.assign(new url.Url(), parseTests[u]); 1032 1033 Object.keys(actual).forEach(function(i) { 1034 if (expected[i] === undefined && actual[i] === null) { 1035 expected[i] = null; 1036 } 1037 }); 1038 1039 assert.deepStrictEqual( 1040 actual, 1041 expected, 1042 `parsing ${u} and expected ${inspect(expected)} but got ${inspect(actual)}` 1043 ); 1044 assert.deepStrictEqual( 1045 spaced, 1046 expected, 1047 `expected ${inspect(expected)}, got ${inspect(spaced)}` 1048 ); 1049 1050 expected = parseTests[u].href; 1051 actual = url.format(parseTests[u]); 1052 1053 assert.strictEqual(actual, expected, 1054 `format(${u}) == ${u}\nactual:${actual}`); 1055} 1056 1057{ 1058 const parsed = url.parse('http://nodejs.org/') 1059 .resolveObject('jAvascript:alert(1);a=\x27@white-listed.com\x27'); 1060 1061 const expected = Object.assign(new url.Url(), { 1062 protocol: 'javascript:', 1063 slashes: null, 1064 auth: null, 1065 host: null, 1066 port: null, 1067 hostname: null, 1068 hash: null, 1069 search: null, 1070 query: null, 1071 pathname: "alert(1);a='@white-listed.com'", 1072 path: "alert(1);a='@white-listed.com'", 1073 href: "javascript:alert(1);a='@white-listed.com'" 1074 }); 1075 1076 assert.deepStrictEqual(parsed, expected); 1077} 1078