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