1'use strict'; 2require('../common'); 3const assert = require('assert'); 4const inspect = require('util').inspect; 5const url = require('url'); 6 7// When source is false 8assert.strictEqual(url.resolveObject('', 'foo'), 'foo'); 9 10// [from, path, expected] 11const relativeTests = [ 12 ['/foo/bar/baz', 'quux', '/foo/bar/quux'], 13 ['/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'], 14 ['/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'], 15 ['/foo/bar/baz', '../quux/baz', '/foo/quux/baz'], 16 ['/foo/bar/baz', '/bar', '/bar'], 17 ['/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'], 18 ['/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'], 19 ['/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'], 20 ['/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'], 21 ['/foo', '.', '/'], 22 ['/foo', '..', '/'], 23 ['/foo/', '.', '/foo/'], 24 ['/foo/', '..', '/'], 25 ['/foo/bar', '.', '/foo/'], 26 ['/foo/bar', '..', '/'], 27 ['/foo/bar/', '.', '/foo/bar/'], 28 ['/foo/bar/', '..', '/foo/'], 29 ['foo/bar', '../../../baz', '../../baz'], 30 ['foo/bar/', '../../../baz', '../baz'], 31 ['http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'], 32 ['http://example.com/b//c//d;p?q#blarg', 33 'https:/p/a/t/h?s#hash2', 34 'https://p/a/t/h?s#hash2'], 35 ['http://example.com/b//c//d;p?q#blarg', 36 'https://u:p@h.com/p/a/t/h?s#hash2', 37 'https://u:p@h.com/p/a/t/h?s#hash2'], 38 ['http://example.com/b//c//d;p?q#blarg', 39 'https:/a/b/c/d', 40 'https://a/b/c/d'], 41 ['http://example.com/b//c//d;p?q#blarg', 42 'http:#hash2', 43 'http://example.com/b//c//d;p?q#hash2'], 44 ['http://example.com/b//c//d;p?q#blarg', 45 'http:/p/a/t/h?s#hash2', 46 'http://example.com/p/a/t/h?s#hash2'], 47 ['http://example.com/b//c//d;p?q#blarg', 48 'http://u:p@h.com/p/a/t/h?s#hash2', 49 'http://u:p@h.com/p/a/t/h?s#hash2'], 50 ['http://example.com/b//c//d;p?q#blarg', 51 'http:/a/b/c/d', 52 'http://example.com/a/b/c/d'], 53 ['/foo/bar/baz', '/../etc/passwd', '/etc/passwd'], 54 ['http://localhost', 'file:///Users/foo', 'file:///Users/foo'], 55 ['http://localhost', 'file://foo/Users', 'file://foo/Users'], 56 ['https://registry.npmjs.org', '@foo/bar', 'https://registry.npmjs.org/@foo/bar'], 57]; 58relativeTests.forEach(function(relativeTest) { 59 const a = url.resolve(relativeTest[0], relativeTest[1]); 60 const e = relativeTest[2]; 61 assert.strictEqual(a, e, 62 `resolve(${relativeTest[0]}, ${relativeTest[1]})` + 63 ` == ${e}\n actual=${a}`); 64}); 65 66// 67// Tests below taken from Chiron 68// http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js 69// 70// Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal> 71// used with permission under MIT License 72// 73// Changes marked with @isaacs 74 75const bases = [ 76 'http://a/b/c/d;p?q', 77 'http://a/b/c/d;p?q=1/2', 78 'http://a/b/c/d;p=1/2?q', 79 'fred:///s//a/b/c', 80 'http:///s//a/b/c', 81]; 82 83// [to, from, result] 84const relativeTests2 = [ 85 // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html 86 ['../c', 'foo:a/b', 'foo:c'], 87 ['foo:.', 'foo:a', 'foo:'], 88 ['/foo/../../../bar', 'zz:abc', 'zz:/bar'], 89 ['/foo/../bar', 'zz:abc', 'zz:/bar'], 90 // @isaacs Disagree. Not how web browsers resolve this. 91 ['foo/../../../bar', 'zz:abc', 'zz:bar'], 92 // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added 93 ['foo/../bar', 'zz:abc', 'zz:bar'], 94 ['zz:.', 'zz:abc', 'zz:'], 95 ['/.', bases[0], 'http://a/'], 96 ['/.foo', bases[0], 'http://a/.foo'], 97 ['.foo', bases[0], 'http://a/b/c/.foo'], 98 99 // http://gbiv.com/protocols/uri/test/rel_examples1.html 100 // examples from RFC 2396 101 ['g:h', bases[0], 'g:h'], 102 ['g', bases[0], 'http://a/b/c/g'], 103 ['./g', bases[0], 'http://a/b/c/g'], 104 ['g/', bases[0], 'http://a/b/c/g/'], 105 ['/g', bases[0], 'http://a/g'], 106 ['//g', bases[0], 'http://g/'], 107 // Changed with RFC 2396bis 108 // ('?y', bases[0], 'http://a/b/c/d;p?y'], 109 ['?y', bases[0], 'http://a/b/c/d;p?y'], 110 ['g?y', bases[0], 'http://a/b/c/g?y'], 111 // Changed with RFC 2396bis 112 // ('#s', bases[0], CURRENT_DOC_URI + '#s'], 113 ['#s', bases[0], 'http://a/b/c/d;p?q#s'], 114 ['g#s', bases[0], 'http://a/b/c/g#s'], 115 ['g?y#s', bases[0], 'http://a/b/c/g?y#s'], 116 [';x', bases[0], 'http://a/b/c/;x'], 117 ['g;x', bases[0], 'http://a/b/c/g;x'], 118 ['g;x?y#s', bases[0], 'http://a/b/c/g;x?y#s'], 119 // Changed with RFC 2396bis 120 // ('', bases[0], CURRENT_DOC_URI], 121 ['', bases[0], 'http://a/b/c/d;p?q'], 122 ['.', bases[0], 'http://a/b/c/'], 123 ['./', bases[0], 'http://a/b/c/'], 124 ['..', bases[0], 'http://a/b/'], 125 ['../', bases[0], 'http://a/b/'], 126 ['../g', bases[0], 'http://a/b/g'], 127 ['../..', bases[0], 'http://a/'], 128 ['../../', bases[0], 'http://a/'], 129 ['../../g', bases[0], 'http://a/g'], 130 ['../../../g', bases[0], ('http://a/../g', 'http://a/g')], 131 ['../../../../g', bases[0], ('http://a/../../g', 'http://a/g')], 132 // Changed with RFC 2396bis 133 // ('/./g', bases[0], 'http://a/./g'], 134 ['/./g', bases[0], 'http://a/g'], 135 // Changed with RFC 2396bis 136 // ('/../g', bases[0], 'http://a/../g'], 137 ['/../g', bases[0], 'http://a/g'], 138 ['g.', bases[0], 'http://a/b/c/g.'], 139 ['.g', bases[0], 'http://a/b/c/.g'], 140 ['g..', bases[0], 'http://a/b/c/g..'], 141 ['..g', bases[0], 'http://a/b/c/..g'], 142 ['./../g', bases[0], 'http://a/b/g'], 143 ['./g/.', bases[0], 'http://a/b/c/g/'], 144 ['g/./h', bases[0], 'http://a/b/c/g/h'], 145 ['g/../h', bases[0], 'http://a/b/c/h'], 146 ['g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'], 147 ['g;x=1/../y', bases[0], 'http://a/b/c/y'], 148 ['g?y/./x', bases[0], 'http://a/b/c/g?y/./x'], 149 ['g?y/../x', bases[0], 'http://a/b/c/g?y/../x'], 150 ['g#s/./x', bases[0], 'http://a/b/c/g#s/./x'], 151 ['g#s/../x', bases[0], 'http://a/b/c/g#s/../x'], 152 ['http:g', bases[0], ('http:g', 'http://a/b/c/g')], 153 ['http:', bases[0], ('http:', bases[0])], 154 // Not sure where this one originated 155 ['/a/b/c/./../../g', bases[0], 'http://a/a/g'], 156 157 // http://gbiv.com/protocols/uri/test/rel_examples2.html 158 // slashes in base URI's query args 159 ['g', bases[1], 'http://a/b/c/g'], 160 ['./g', bases[1], 'http://a/b/c/g'], 161 ['g/', bases[1], 'http://a/b/c/g/'], 162 ['/g', bases[1], 'http://a/g'], 163 ['//g', bases[1], 'http://g/'], 164 // Changed in RFC 2396bis 165 // ('?y', bases[1], 'http://a/b/c/?y'], 166 ['?y', bases[1], 'http://a/b/c/d;p?y'], 167 ['g?y', bases[1], 'http://a/b/c/g?y'], 168 ['g?y/./x', bases[1], 'http://a/b/c/g?y/./x'], 169 ['g?y/../x', bases[1], 'http://a/b/c/g?y/../x'], 170 ['g#s', bases[1], 'http://a/b/c/g#s'], 171 ['g#s/./x', bases[1], 'http://a/b/c/g#s/./x'], 172 ['g#s/../x', bases[1], 'http://a/b/c/g#s/../x'], 173 ['./', bases[1], 'http://a/b/c/'], 174 ['../', bases[1], 'http://a/b/'], 175 ['../g', bases[1], 'http://a/b/g'], 176 ['../../', bases[1], 'http://a/'], 177 ['../../g', bases[1], 'http://a/g'], 178 179 // http://gbiv.com/protocols/uri/test/rel_examples3.html 180 // slashes in path params 181 // all of these changed in RFC 2396bis 182 ['g', bases[2], 'http://a/b/c/d;p=1/g'], 183 ['./g', bases[2], 'http://a/b/c/d;p=1/g'], 184 ['g/', bases[2], 'http://a/b/c/d;p=1/g/'], 185 ['g?y', bases[2], 'http://a/b/c/d;p=1/g?y'], 186 [';x', bases[2], 'http://a/b/c/d;p=1/;x'], 187 ['g;x', bases[2], 'http://a/b/c/d;p=1/g;x'], 188 ['g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'], 189 ['g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'], 190 ['./', bases[2], 'http://a/b/c/d;p=1/'], 191 ['../', bases[2], 'http://a/b/c/'], 192 ['../g', bases[2], 'http://a/b/c/g'], 193 ['../../', bases[2], 'http://a/b/'], 194 ['../../g', bases[2], 'http://a/b/g'], 195 196 // http://gbiv.com/protocols/uri/test/rel_examples4.html 197 // double and triple slash, unknown scheme 198 ['g:h', bases[3], 'g:h'], 199 ['g', bases[3], 'fred:///s//a/b/g'], 200 ['./g', bases[3], 'fred:///s//a/b/g'], 201 ['g/', bases[3], 'fred:///s//a/b/g/'], 202 ['/g', bases[3], 'fred:///g'], // May change to fred:///s//a/g 203 ['//g', bases[3], 'fred://g'], // May change to fred:///s//g 204 ['//g/x', bases[3], 'fred://g/x'], // May change to fred:///s//g/x 205 ['///g', bases[3], 'fred:///g'], 206 ['./', bases[3], 'fred:///s//a/b/'], 207 ['../', bases[3], 'fred:///s//a/'], 208 ['../g', bases[3], 'fred:///s//a/g'], 209 210 ['../../', bases[3], 'fred:///s//'], 211 ['../../g', bases[3], 'fred:///s//g'], 212 ['../../../g', bases[3], 'fred:///s/g'], 213 // May change to fred:///s//a/../../../g 214 ['../../../../g', bases[3], 'fred:///g'], 215 216 // http://gbiv.com/protocols/uri/test/rel_examples5.html 217 // double and triple slash, well-known scheme 218 ['g:h', bases[4], 'g:h'], 219 ['g', bases[4], 'http:///s//a/b/g'], 220 ['./g', bases[4], 'http:///s//a/b/g'], 221 ['g/', bases[4], 'http:///s//a/b/g/'], 222 ['/g', bases[4], 'http:///g'], // May change to http:///s//a/g 223 ['//g', bases[4], 'http://g/'], // May change to http:///s//g 224 ['//g/x', bases[4], 'http://g/x'], // May change to http:///s//g/x 225 ['///g', bases[4], 'http:///g'], 226 ['./', bases[4], 'http:///s//a/b/'], 227 ['../', bases[4], 'http:///s//a/'], 228 ['../g', bases[4], 'http:///s//a/g'], 229 ['../../', bases[4], 'http:///s//'], 230 ['../../g', bases[4], 'http:///s//g'], 231 // May change to http:///s//a/../../g 232 ['../../../g', bases[4], 'http:///s/g'], 233 // May change to http:///s//a/../../../g 234 ['../../../../g', bases[4], 'http:///g'], 235 236 // From Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py 237 ['bar:abc', 'foo:xyz', 'bar:abc'], 238 ['../abc', 'http://example/x/y/z', 'http://example/x/abc'], 239 ['http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'], 240 ['../r', 'http://ex/x/y/z', 'http://ex/x/r'], 241 ['q/r', 'http://ex/x/y', 'http://ex/x/q/r'], 242 ['q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'], 243 ['q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'], 244 ['ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'], 245 ['', 'http://ex/x/y', 'http://ex/x/y'], 246 ['', 'http://ex/x/y/', 'http://ex/x/y/'], 247 ['', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'], 248 ['z/', 'http://ex/x/y/', 'http://ex/x/y/z/'], 249 ['#Animal', 250 'file:/swap/test/animal.rdf', 251 'file:/swap/test/animal.rdf#Animal'], 252 ['../abc', 'file:/e/x/y/z', 'file:/e/x/abc'], 253 ['/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'], 254 ['../r', 'file:/ex/x/y/z', 'file:/ex/x/r'], 255 ['/r', 'file:/ex/x/y/z', 'file:/r'], 256 ['q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'], 257 ['q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'], 258 ['q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'], 259 ['q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'], 260 ['ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'], 261 ['', 'file:/ex/x/y', 'file:/ex/x/y'], 262 ['', 'file:/ex/x/y/', 'file:/ex/x/y/'], 263 ['', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'], 264 ['z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'], 265 ['file://meetings.example.com/cal#m1', 266 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3', 267 'file://meetings.example.com/cal#m1'], 268 ['file://meetings.example.com/cal#m1', 269 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3', 270 'file://meetings.example.com/cal#m1'], 271 ['./#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'], 272 ['./#', 'file:/some/dir/foo', 'file:/some/dir/#'], 273 // Ryan Lee 274 ['./', 'http://example/x/abc.efg', 'http://example/x/'], 275 276 277 // Graham Klyne's tests 278 // http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls 279 // 01-31 are from Connelly's cases 280 281 // 32-49 282 ['./q:r', 'http://ex/x/y', 'http://ex/x/q:r'], 283 ['./p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'], 284 ['?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'], 285 ['y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'], 286 ['local/qual@domain.org#frag', 287 'mailto:local', 288 'mailto:local/qual@domain.org#frag'], 289 ['more/qual2@domain2.org#frag', 290 'mailto:local/qual1@domain1.org', 291 'mailto:local/more/qual2@domain2.org#frag'], 292 ['y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'], 293 ['/x/y?q', 'http://ex?p', 'http://ex/x/y?q'], 294 ['c/d', 'foo:a/b', 'foo:a/c/d'], 295 ['/c/d', 'foo:a/b', 'foo:/c/d'], 296 ['', 'foo:a/b?c#d', 'foo:a/b?c'], 297 ['b/c', 'foo:a', 'foo:b/c'], 298 ['../b/c', 'foo:/a/y/z', 'foo:/a/b/c'], 299 ['./b/c', 'foo:a', 'foo:b/c'], 300 ['/./b/c', 'foo:a', 'foo:/b/c'], 301 ['../../d', 'foo://a//b/c', 'foo://a/d'], 302 ['.', 'foo:a', 'foo:'], 303 ['..', 'foo:a', 'foo:'], 304 305 // 50-57[cf. TimBL comments -- 306 // http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html, 307 // http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html) 308 ['abc', 'http://example/x/y%2Fz', 'http://example/x/abc'], 309 ['../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'], 310 ['../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'], 311 ['abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'], 312 ['q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'], 313 ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'], 314 ['/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'], 315 ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'], 316 317 // 70-77 318 ['local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'], 319 ['local2@domain2?query2', 320 'mailto:local1@domain1', 321 'mailto:local2@domain2?query2'], 322 ['local2@domain2?query2', 323 'mailto:local1@domain1?query1', 324 'mailto:local2@domain2?query2'], 325 ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'], 326 ['local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'], 327 ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'], 328 ['http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'], 329 ['http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'], 330 331 // 82-88 332 // @isaacs Disagree. Not how browsers do it. 333 // ['http:this', 'http://example.org/base/uri', 'http:this'], 334 // @isaacs Added 335 ['http:this', 'http://example.org/base/uri', 'http://example.org/base/this'], 336 ['http:this', 'http:base', 'http:this'], 337 ['.//g', 'f:/a', 'f://g'], 338 ['b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'], 339 ['m2@example.ord/c2@example.org', 340 'mid:m@example.ord/c@example.org', 341 'mid:m@example.ord/m2@example.ord/c2@example.org'], 342 ['mini1.xml', 343 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/', 344 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'], 345 ['../b/c', 'foo:a/y/z', 'foo:a/b/c'], 346 347 // changeing auth 348 ['http://diff:auth@www.example.com', 349 'http://asdf:qwer@www.example.com', 350 'http://diff:auth@www.example.com/'], 351 352 // changing port 353 ['https://example.com:81/', 354 'https://example.com:82/', 355 'https://example.com:81/'], 356 357 // https://github.com/nodejs/node/issues/1435 358 ['https://another.host.com/', 359 'https://user:password@example.org/', 360 'https://another.host.com/'], 361 ['//another.host.com/', 362 'https://user:password@example.org/', 363 'https://another.host.com/'], 364 ['http://another.host.com/', 365 'https://user:password@example.org/', 366 'http://another.host.com/'], 367 ['mailto:another.host.com', 368 'mailto:user@example.org', 369 'mailto:another.host.com'], 370 ['https://example.com/foo', 371 'https://user:password@example.com', 372 'https://user:password@example.com/foo'], 373 374 // No path at all 375 ['#hash1', '#hash2', '#hash1'], 376]; 377relativeTests2.forEach(function(relativeTest) { 378 const a = url.resolve(relativeTest[1], relativeTest[0]); 379 const e = url.format(relativeTest[2]); 380 assert.strictEqual(a, e, 381 `resolve(${relativeTest[0]}, ${relativeTest[1]})` + 382 ` == ${e}\n actual=${a}`); 383}); 384 385// If format and parse are inverse operations then 386// resolveObject(parse(x), y) == parse(resolve(x, y)) 387 388// format: [from, path, expected] 389relativeTests.forEach(function(relativeTest) { 390 let actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]); 391 let expected = url.parse(relativeTest[2]); 392 393 394 assert.deepStrictEqual(actual, expected); 395 396 expected = relativeTest[2]; 397 actual = url.format(actual); 398 399 assert.strictEqual(actual, expected, 400 `format(${actual}) == ${expected}\n` + 401 `actual: ${actual}`); 402}); 403 404// format: [to, from, result] 405// the test: ['.//g', 'f:/a', 'f://g'] is a fundamental problem 406// url.parse('f:/a') does not have a host 407// url.resolve('f:/a', './/g') does not have a host because you have moved 408// down to the g directory. i.e. f: //g, however when this url is parsed 409// f:// will indicate that the host is g which is not the case. 410// it is unclear to me how to keep this information from being lost 411// it may be that a pathname of ////g should collapse to /g but this seems 412// to be a lot of work for an edge case. Right now I remove the test 413if (relativeTests2[181][0] === './/g' && 414 relativeTests2[181][1] === 'f:/a' && 415 relativeTests2[181][2] === 'f://g') { 416 relativeTests2.splice(181, 1); 417} 418relativeTests2.forEach(function(relativeTest) { 419 let actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]); 420 let expected = url.parse(relativeTest[2]); 421 422 assert.deepStrictEqual( 423 actual, 424 expected, 425 `expected ${inspect(expected)} but got ${inspect(actual)}` 426 ); 427 428 expected = url.format(relativeTest[2]); 429 actual = url.format(actual); 430 431 assert.strictEqual(actual, expected, 432 `format(${relativeTest[1]}) == ${expected}\n` + 433 `actual: ${actual}`); 434}); 435