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