mdurl-rb 1.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,704 @@
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
+ # URLs to parse, and expected data
23
+ # { url : parsed }
24
+
25
+ URL_TEST_DATA = {
26
+ '//some_path' => {
27
+ 'pathname' => '//some_path'
28
+ },
29
+
30
+ 'HTTP://www.example.com/' => {
31
+ 'protocol' => 'HTTP:',
32
+ 'slashes' => true,
33
+ 'hostname' => 'www.example.com',
34
+ 'pathname' => '/'
35
+ },
36
+
37
+ 'HTTP://www.example.com' => {
38
+ 'protocol' => 'HTTP:',
39
+ 'slashes' => true,
40
+ 'hostname' => 'www.example.com',
41
+ 'pathname' => ''
42
+ },
43
+
44
+ 'http://www.ExAmPlE.com/' => {
45
+ 'protocol' => 'http:',
46
+ 'slashes' => true,
47
+ 'hostname' => 'www.ExAmPlE.com',
48
+ 'pathname' => '/'
49
+ },
50
+
51
+ 'http://user:pw@www.ExAmPlE.com/' => {
52
+ 'protocol' => 'http:',
53
+ 'slashes' => true,
54
+ 'auth' => 'user:pw',
55
+ 'hostname' => 'www.ExAmPlE.com',
56
+ 'pathname' => '/'
57
+ },
58
+
59
+ 'http://USER:PW@www.ExAmPlE.com/' => {
60
+ 'protocol' => 'http:',
61
+ 'slashes' => true,
62
+ 'auth' => 'USER:PW',
63
+ 'hostname' => 'www.ExAmPlE.com',
64
+ 'pathname' => '/'
65
+ },
66
+
67
+ 'http://user@www.example.com/' => {
68
+ 'protocol' => 'http:',
69
+ 'slashes' => true,
70
+ 'auth' => 'user',
71
+ 'hostname' => 'www.example.com',
72
+ 'pathname' => '/'
73
+ },
74
+
75
+ 'http://user%3Apw@www.example.com/' => {
76
+ 'protocol' => 'http:',
77
+ 'slashes' => true,
78
+ 'auth' => 'user%3Apw',
79
+ 'hostname' => 'www.example.com',
80
+ 'pathname' => '/'
81
+ },
82
+
83
+ 'http://x.com/path?that\'s#all, folks' => {
84
+ 'protocol' => 'http:',
85
+ 'hostname' => 'x.com',
86
+ 'slashes' => true,
87
+ 'search' => '?that\'s',
88
+ 'pathname' => '/path',
89
+ 'hash' => '#all, folks'
90
+ },
91
+
92
+ 'HTTP://X.COM/Y' => {
93
+ 'protocol' => 'HTTP:',
94
+ 'slashes' => true,
95
+ 'hostname' => 'X.COM',
96
+ 'pathname' => '/Y'
97
+ },
98
+
99
+ # + not an invalid host character
100
+ # per https://url.spec.whatwg.org/#host-parsing
101
+ 'http://x.y.com+a/b/c' => {
102
+ 'protocol' => 'http:',
103
+ 'slashes' => true,
104
+ 'hostname' => 'x.y.com+a',
105
+ 'pathname' => '/b/c'
106
+ },
107
+
108
+ # an unexpected invalid char in the hostname.
109
+ 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i' => {
110
+ 'protocol' => 'HtTp:',
111
+ 'slashes' => true,
112
+ 'hostname' => 'x.y.cOm',
113
+ 'pathname' => ';a/b/c',
114
+ 'search' => '?d=e',
115
+ 'hash' => '#f g<h>i'
116
+ },
117
+
118
+ # make sure that we don't accidentally lcast the path parts.
119
+ 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i' => {
120
+ 'protocol' => 'HtTp:',
121
+ 'slashes' => true,
122
+ 'hostname' => 'x.y.cOm',
123
+ 'pathname' => ';A/b/c',
124
+ 'search' => '?d=e',
125
+ 'hash' => '#f g<h>i'
126
+ },
127
+
128
+ 'http://x...y...#p' => {
129
+ 'protocol' => 'http:',
130
+ 'slashes' => true,
131
+ 'hostname' => 'x...y...',
132
+ 'hash' => '#p',
133
+ 'pathname' => ''
134
+ },
135
+
136
+ 'http://x/p/"quoted"' => {
137
+ 'protocol' => 'http:',
138
+ 'slashes' => true,
139
+ 'hostname' => 'x',
140
+ 'pathname' => '/p/"quoted"'
141
+ },
142
+
143
+ '<http://goo.corn/bread> Is a URL!' => {
144
+ 'pathname' => '<http://goo.corn/bread> Is a URL!'
145
+ },
146
+
147
+ 'http://www.narwhaljs.org/blog/categories?id=news' => {
148
+ 'protocol' => 'http:',
149
+ 'slashes' => true,
150
+ 'hostname' => 'www.narwhaljs.org',
151
+ 'search' => '?id=news',
152
+ 'pathname' => '/blog/categories'
153
+ },
154
+
155
+ 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=' => {
156
+ 'protocol' => 'http:',
157
+ 'slashes' => true,
158
+ 'hostname' => 'mt0.google.com',
159
+ 'pathname' => '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
160
+ },
161
+
162
+ 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' => {
163
+ 'protocol' => 'http:',
164
+ 'slashes' => true,
165
+ 'hostname' => 'mt0.google.com',
166
+ 'search' => '???&hl=en&src=api&x=2&y=2&z=3&s=',
167
+ 'pathname' => '/vt/lyrs=m@114'
168
+ },
169
+
170
+ 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' =>
171
+ {
172
+ 'protocol' => 'http:',
173
+ 'slashes' => true,
174
+ 'auth' => 'user:pass',
175
+ 'hostname' => 'mt0.google.com',
176
+ 'search' => '???&hl=en&src=api&x=2&y=2&z=3&s=',
177
+ 'pathname' => '/vt/lyrs=m@114'
178
+ },
179
+
180
+ 'file:///etc/passwd' => {
181
+ 'slashes' => true,
182
+ 'protocol' => 'file:',
183
+ 'pathname' => '/etc/passwd',
184
+ 'hostname' => ''
185
+ },
186
+
187
+ 'file://localhost/etc/passwd' => {
188
+ 'protocol' => 'file:',
189
+ 'slashes' => true,
190
+ 'pathname' => '/etc/passwd',
191
+ 'hostname' => 'localhost'
192
+ },
193
+
194
+ 'file://foo/etc/passwd' => {
195
+ 'protocol' => 'file:',
196
+ 'slashes' => true,
197
+ 'pathname' => '/etc/passwd',
198
+ 'hostname' => 'foo'
199
+ },
200
+
201
+ 'file:///etc/node/' => {
202
+ 'slashes' => true,
203
+ 'protocol' => 'file:',
204
+ 'pathname' => '/etc/node/',
205
+ 'hostname' => ''
206
+ },
207
+
208
+ 'file://localhost/etc/node/' => {
209
+ 'protocol' => 'file:',
210
+ 'slashes' => true,
211
+ 'pathname' => '/etc/node/',
212
+ 'hostname' => 'localhost'
213
+ },
214
+
215
+ 'file://foo/etc/node/' => {
216
+ 'protocol' => 'file:',
217
+ 'slashes' => true,
218
+ 'pathname' => '/etc/node/',
219
+ 'hostname' => 'foo'
220
+ },
221
+
222
+ 'http:/baz/../foo/bar' => {
223
+ 'protocol' => 'http:',
224
+ 'pathname' => '/baz/../foo/bar'
225
+ },
226
+
227
+ 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag' => {
228
+ 'protocol' => 'http:',
229
+ 'slashes' => true,
230
+ 'auth' => 'user:pass',
231
+ 'port' => '8000',
232
+ 'hostname' => 'example.com',
233
+ 'hash' => '#frag',
234
+ 'search' => '?baz=quux',
235
+ 'pathname' => '/foo/bar'
236
+ },
237
+
238
+ '//user:pass@example.com:8000/foo/bar?baz=quux#frag' => {
239
+ 'slashes' => true,
240
+ 'auth' => 'user:pass',
241
+ 'port' => '8000',
242
+ 'hostname' => 'example.com',
243
+ 'hash' => '#frag',
244
+ 'search' => '?baz=quux',
245
+ 'pathname' => '/foo/bar'
246
+ },
247
+
248
+ '/foo/bar?baz=quux#frag' => {
249
+ 'hash' => '#frag',
250
+ 'search' => '?baz=quux',
251
+ 'pathname' => '/foo/bar'
252
+ },
253
+
254
+ 'http:/foo/bar?baz=quux#frag' => {
255
+ 'protocol' => 'http:',
256
+ 'hash' => '#frag',
257
+ 'search' => '?baz=quux',
258
+ 'pathname' => '/foo/bar'
259
+ },
260
+
261
+ 'mailto:foo@bar.com?subject=hello' => {
262
+ 'protocol' => 'mailto:',
263
+ 'auth' => 'foo',
264
+ 'hostname' => 'bar.com',
265
+ 'search' => '?subject=hello',
266
+ 'pathname' => ''
267
+ },
268
+
269
+ 'javascript:alert(\'hello\');' => {
270
+ 'protocol' => 'javascript:',
271
+ 'pathname' => 'alert(\'hello\');'
272
+ },
273
+
274
+ 'xmpp:isaacschlueter@jabber.org' => {
275
+ 'protocol' => 'xmpp:',
276
+ 'auth' => 'isaacschlueter',
277
+ 'hostname' => 'jabber.org'
278
+ },
279
+
280
+ 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar' => {
281
+ 'protocol' => 'http:',
282
+ 'slashes' => true,
283
+ 'auth' => 'atpass:foo%40bar',
284
+ 'hostname' => '127.0.0.1',
285
+ 'port' => '8080',
286
+ 'pathname' => '/path',
287
+ 'search' => '?search=foo',
288
+ 'hash' => '#bar'
289
+ },
290
+
291
+ 'svn+ssh://foo/bar' => {
292
+ 'hostname' => 'foo',
293
+ 'protocol' => 'svn+ssh:',
294
+ 'pathname' => '/bar',
295
+ 'slashes' => true
296
+ },
297
+
298
+ 'dash-test://foo/bar' => {
299
+ 'hostname' => 'foo',
300
+ 'protocol' => 'dash-test:',
301
+ 'pathname' => '/bar',
302
+ 'slashes' => true
303
+ },
304
+
305
+ 'dash-test:foo/bar' => {
306
+ 'hostname' => 'foo',
307
+ 'protocol' => 'dash-test:',
308
+ 'pathname' => '/bar'
309
+ },
310
+
311
+ 'dot.test://foo/bar' => {
312
+ 'hostname' => 'foo',
313
+ 'protocol' => 'dot.test:',
314
+ 'pathname' => '/bar',
315
+ 'slashes' => true
316
+ },
317
+
318
+ 'dot.test:foo/bar' => {
319
+ 'hostname' => 'foo',
320
+ 'protocol' => 'dot.test:',
321
+ 'pathname' => '/bar'
322
+ },
323
+
324
+ # IDNA tests
325
+ 'http://www.日本語.com/' => {
326
+ 'protocol' => 'http:',
327
+ 'slashes' => true,
328
+ 'hostname' => 'www.日本語.com',
329
+ 'pathname' => '/'
330
+ },
331
+
332
+ 'http://example.Bücher.com/' => {
333
+ 'protocol' => 'http:',
334
+ 'slashes' => true,
335
+ 'hostname' => 'example.Bücher.com',
336
+ 'pathname' => '/'
337
+ },
338
+
339
+ 'http://www.Äffchen.com/' => {
340
+ 'protocol' => 'http:',
341
+ 'slashes' => true,
342
+ 'hostname' => 'www.Äffchen.com',
343
+ 'pathname' => '/'
344
+ },
345
+
346
+ 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i' => {
347
+ 'protocol' => 'http:',
348
+ 'slashes' => true,
349
+ 'hostname' => 'www.Äffchen.cOm',
350
+ 'pathname' => ';A/b/c',
351
+ 'search' => '?d=e',
352
+ 'hash' => '#f g<h>i'
353
+ },
354
+
355
+ 'http://SÉLIER.COM/' => {
356
+ 'protocol' => 'http:',
357
+ 'slashes' => true,
358
+ 'hostname' => 'SÉLIER.COM',
359
+ 'pathname' => '/'
360
+ },
361
+
362
+ 'http://ليهمابتكلموشعربي؟.ي؟/' => {
363
+ 'protocol' => 'http:',
364
+ 'slashes' => true,
365
+ 'hostname' => 'ليهمابتكلموشعربي؟.ي؟',
366
+ 'pathname' => '/'
367
+ },
368
+
369
+ 'http://➡.ws/➡' => {
370
+ 'protocol' => 'http:',
371
+ 'slashes' => true,
372
+ 'hostname' => '➡.ws',
373
+ 'pathname' => '/➡'
374
+ },
375
+
376
+ 'http://bucket_name.s3.amazonaws.com/image.jpg' => {
377
+ 'protocol' => 'http:',
378
+ 'slashes' => true,
379
+ 'hostname' => 'bucket_name.s3.amazonaws.com',
380
+ 'pathname' => '/image.jpg'
381
+ },
382
+
383
+ 'git+http://github.com/joyent/node.git' => {
384
+ 'protocol' => 'git+http:',
385
+ 'slashes' => true,
386
+ 'hostname' => 'github.com',
387
+ 'pathname' => '/joyent/node.git'
388
+ },
389
+
390
+ # if local1@domain1 is uses as a relative URL it may
391
+ # be parse into auth@hostname, but here there is no
392
+ # way to make it work in url.parse, I add the test to be explicit
393
+ 'local1@domain1' => {
394
+ 'pathname' => 'local1@domain1'
395
+ },
396
+
397
+ # While this may seem counter-intuitive, a browser will parse
398
+ # <a href='www.google.com'> as a path.
399
+ 'www.example.com' => {
400
+ 'pathname' => 'www.example.com'
401
+ },
402
+
403
+ # ipv6 support
404
+ '[fe80::1]' => {
405
+ 'pathname' => '[fe80::1]'
406
+ },
407
+
408
+ 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]' => {
409
+ 'protocol' => 'coap:',
410
+ 'slashes' => true,
411
+ 'hostname' => 'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210'
412
+ },
413
+
414
+ 'coap://[1080:0:0:0:8:800:200C:417A]:61616/' => {
415
+ 'protocol' => 'coap:',
416
+ 'slashes' => true,
417
+ 'port' => '61616',
418
+ 'hostname' => '1080:0:0:0:8:800:200C:417A',
419
+ 'pathname' => '/'
420
+ },
421
+
422
+ 'http://user:password@[3ffe:2a00:100:7031::1]:8080' => {
423
+ 'protocol' => 'http:',
424
+ 'slashes' => true,
425
+ 'auth' => 'user:password',
426
+ 'port' => '8080',
427
+ 'hostname' => '3ffe:2a00:100:7031::1',
428
+ 'pathname' => ''
429
+ },
430
+
431
+ 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature' => {
432
+ 'protocol' => 'coap:',
433
+ 'slashes' => true,
434
+ 'auth' => 'u:p',
435
+ 'port' => '61616',
436
+ 'hostname' => '::192.9.5.5',
437
+ 'search' => '?n=Temperature',
438
+ 'pathname' => '/.well-known/r'
439
+ },
440
+
441
+ # empty port
442
+ 'http://example.com:' => {
443
+ 'protocol' => 'http:',
444
+ 'slashes' => true,
445
+ 'hostname' => 'example.com',
446
+ 'pathname' => ':'
447
+ },
448
+
449
+ 'http://example.com:/a/b.html' => {
450
+ 'protocol' => 'http:',
451
+ 'slashes' => true,
452
+ 'hostname' => 'example.com',
453
+ 'pathname' => ':/a/b.html'
454
+ },
455
+
456
+ 'http://example.com:?a=b' => {
457
+ 'protocol' => 'http:',
458
+ 'slashes' => true,
459
+ 'hostname' => 'example.com',
460
+ 'search' => '?a=b',
461
+ 'pathname' => ':'
462
+ },
463
+
464
+ 'http://example.com:#abc' => {
465
+ 'protocol' => 'http:',
466
+ 'slashes' => true,
467
+ 'hostname' => 'example.com',
468
+ 'hash' => '#abc',
469
+ 'pathname' => ':'
470
+ },
471
+
472
+ 'http://[fe80::1]:/a/b?a=b#abc' => {
473
+ 'protocol' => 'http:',
474
+ 'slashes' => true,
475
+ 'hostname' => 'fe80::1',
476
+ 'search' => '?a=b',
477
+ 'hash' => '#abc',
478
+ 'pathname' => ':/a/b'
479
+ },
480
+
481
+ 'http://-lovemonsterz.tumblr.com/rss' => {
482
+ 'protocol' => 'http:',
483
+ 'slashes' => true,
484
+ 'hostname' => '-lovemonsterz.tumblr.com',
485
+ 'pathname' => '/rss'
486
+ },
487
+
488
+ 'http://-lovemonsterz.tumblr.com:80/rss' => {
489
+ 'protocol' => 'http:',
490
+ 'slashes' => true,
491
+ 'port' => '80',
492
+ 'hostname' => '-lovemonsterz.tumblr.com',
493
+ 'pathname' => '/rss'
494
+ },
495
+
496
+ 'http://user:pass@-lovemonsterz.tumblr.com/rss' => {
497
+ 'protocol' => 'http:',
498
+ 'slashes' => true,
499
+ 'auth' => 'user:pass',
500
+ 'hostname' => '-lovemonsterz.tumblr.com',
501
+ 'pathname' => '/rss'
502
+ },
503
+
504
+ 'http://user:pass@-lovemonsterz.tumblr.com:80/rss' => {
505
+ 'protocol' => 'http:',
506
+ 'slashes' => true,
507
+ 'auth' => 'user:pass',
508
+ 'port' => '80',
509
+ 'hostname' => '-lovemonsterz.tumblr.com',
510
+ 'pathname' => '/rss'
511
+ },
512
+
513
+ 'http://_jabber._tcp.google.com/test' => {
514
+ 'protocol' => 'http:',
515
+ 'slashes' => true,
516
+ 'hostname' => '_jabber._tcp.google.com',
517
+ 'pathname' => '/test'
518
+ },
519
+
520
+ 'http://user:pass@_jabber._tcp.google.com/test' => {
521
+ 'protocol' => 'http:',
522
+ 'slashes' => true,
523
+ 'auth' => 'user:pass',
524
+ 'hostname' => '_jabber._tcp.google.com',
525
+ 'pathname' => '/test'
526
+ },
527
+
528
+ 'http://_jabber._tcp.google.com:80/test' => {
529
+ 'protocol' => 'http:',
530
+ 'slashes' => true,
531
+ 'port' => '80',
532
+ 'hostname' => '_jabber._tcp.google.com',
533
+ 'pathname' => '/test'
534
+ },
535
+
536
+ 'http://user:pass@_jabber._tcp.google.com:80/test' => {
537
+ 'protocol' => 'http:',
538
+ 'slashes' => true,
539
+ 'auth' => 'user:pass',
540
+ 'port' => '80',
541
+ 'hostname' => '_jabber._tcp.google.com',
542
+ 'pathname' => '/test'
543
+ },
544
+
545
+ 'http://x:1/\' <>"`/{}|\\^~`/' => {
546
+ 'protocol' => 'http:',
547
+ 'slashes' => true,
548
+ 'port' => '1',
549
+ 'hostname' => 'x',
550
+ 'pathname' => '/\' <>"`/{}|\\^~`/'
551
+ },
552
+
553
+ 'http://a@b@c/' => {
554
+ 'protocol' => 'http:',
555
+ 'slashes' => true,
556
+ 'auth' => 'a@b',
557
+ 'hostname' => 'c',
558
+ 'pathname' => '/'
559
+ },
560
+
561
+ 'http://a@b?@c' => {
562
+ 'protocol' => 'http:',
563
+ 'slashes' => true,
564
+ 'auth' => 'a',
565
+ 'hostname' => 'b',
566
+ 'pathname' => '',
567
+ 'search' => '?@c'
568
+ },
569
+
570
+ 'http://a\r" \t\n<\'b:b@c\r\nd/e?f' =>{
571
+ 'protocol' => 'http:',
572
+ 'slashes' => true,
573
+ 'auth' => 'a\r" \t\n<\'b:b',
574
+ 'hostname' => 'c',
575
+ 'search' => '?f',
576
+ 'pathname' => '\r\nd/e'
577
+ },
578
+
579
+ # git urls used by npm
580
+ 'git+ssh://git@github.com:npm/npm' => {
581
+ 'protocol' => 'git+ssh:',
582
+ 'slashes' => true,
583
+ 'auth' => 'git',
584
+ 'hostname' => 'github.com',
585
+ 'pathname' => ':npm/npm'
586
+ },
587
+
588
+ 'http://example.com?foo=bar#frag' => {
589
+ 'protocol' => 'http:',
590
+ 'slashes' => true,
591
+ 'hostname' => 'example.com',
592
+ 'hash' => '#frag',
593
+ 'search' => '?foo=bar',
594
+ 'pathname' => ''
595
+ },
596
+
597
+ 'http://example.com?foo=@bar#frag' => {
598
+ 'protocol' => 'http:',
599
+ 'slashes' => true,
600
+ 'hostname' => 'example.com',
601
+ 'hash' => '#frag',
602
+ 'search' => '?foo=@bar',
603
+ 'pathname' => ''
604
+ },
605
+
606
+ 'http://example.com?foo=/bar/#frag' => {
607
+ 'protocol' => 'http:',
608
+ 'slashes' => true,
609
+ 'hostname' => 'example.com',
610
+ 'hash' => '#frag',
611
+ 'search' => '?foo=/bar/',
612
+ 'pathname' => ''
613
+ },
614
+
615
+ 'http://example.com?foo=?bar/#frag' => {
616
+ 'protocol' => 'http:',
617
+ 'slashes' => true,
618
+ 'hostname' => 'example.com',
619
+ 'hash' => '#frag',
620
+ 'search' => '?foo=?bar/',
621
+ 'pathname' => ''
622
+ },
623
+
624
+ 'http://example.com#frag=?bar/#frag' => {
625
+ 'protocol' => 'http:',
626
+ 'slashes' => true,
627
+ 'hostname' => 'example.com',
628
+ 'hash' => '#frag=?bar/#frag',
629
+ 'pathname' => ''
630
+ },
631
+
632
+ 'http://google.com" onload="alert(42)/' => {
633
+ 'hostname' => 'google.com',
634
+ 'protocol' => 'http:',
635
+ 'slashes' => true,
636
+ 'pathname' => '" onload="alert(42)/'
637
+ },
638
+
639
+ 'http://a.com/a/b/c?s#h' => {
640
+ 'protocol' => 'http:',
641
+ 'slashes' => true,
642
+ 'pathname' => '/a/b/c',
643
+ 'hostname' => 'a.com',
644
+ 'hash' => '#h',
645
+ 'search' => '?s'
646
+ },
647
+
648
+ 'http://atpass:foo%40bar@127.0.0.1/' => {
649
+ 'auth' => 'atpass:foo%40bar',
650
+ 'slashes' => true,
651
+ 'hostname' => '127.0.0.1',
652
+ 'protocol' => 'http:',
653
+ 'pathname' => '/'
654
+ },
655
+
656
+ 'http://atslash%2F%40:%2F%40@foo/' => {
657
+ 'auth' => 'atslash%2F%40:%2F%40',
658
+ 'hostname' => 'foo',
659
+ 'protocol' => 'http:',
660
+ 'pathname' => '/',
661
+ 'slashes' => true
662
+ },
663
+
664
+ # ipv6 support
665
+ 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature' => {
666
+ 'protocol' => 'coap:',
667
+ 'auth' => 'u:p',
668
+ 'hostname' => '::1',
669
+ 'port' => '61616',
670
+ 'pathname' => '/.well-known/r',
671
+ 'search' => '?n=Temperature'
672
+ },
673
+
674
+ 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton' => {
675
+ 'hostname' => 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
676
+ 'port' => '61616',
677
+ 'protocol' => 'coap:',
678
+ 'pathname' => '/s/stopButton'
679
+ },
680
+
681
+ # encode context-specific delimiters in path and query, but do not touch
682
+ # other non-delimiter chars like `%`.
683
+ # <https://github.com/joyent/node/issues/4082>
684
+
685
+ # `?` and `#` in path and search
686
+ 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag' => {
687
+ 'protocol' => 'http:',
688
+ 'hostname' => 'ex.com',
689
+ 'hash' => '#frag',
690
+ 'search' => '?abc=the%231?&foo=bar',
691
+ 'pathname' => '/foo%3F100%m%23r',
692
+ 'slashes' => true
693
+ },
694
+
695
+ # `?` and `#` in search only
696
+ 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag' => {
697
+ 'protocol' => 'http:',
698
+ 'hostname' => 'ex.com',
699
+ 'hash' => '#frag',
700
+ 'search' => '?abc=the%231?&foo=bar',
701
+ 'pathname' => '/fooA100%mBr',
702
+ 'slashes' => true
703
+ }
704
+ };