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