You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1599 lines
46 KiB

4 years ago
  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. var assert = require('assert');
  22. var url = require('./url');
  23. // URLs to parse, and expected data
  24. // { url : parsed }
  25. var parseTests = {
  26. '//some_path' : {
  27. 'href': '//some_path',
  28. 'pathname': '//some_path',
  29. 'path': '//some_path'
  30. },
  31. 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h': {
  32. protocol: 'http:',
  33. slashes: true,
  34. host: 'evil-phisher',
  35. hostname: 'evil-phisher',
  36. pathname: '/foo.html',
  37. path: '/foo.html',
  38. hash: '#h%5Ca%5Cs%5Ch',
  39. href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch'
  40. },
  41. 'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': {
  42. protocol: 'http:',
  43. slashes: true,
  44. host: 'evil-phisher',
  45. hostname: 'evil-phisher',
  46. pathname: '/foo.html',
  47. search: '?json=%22%5C%22foo%5C%22%22',
  48. query: 'json=%22%5C%22foo%5C%22%22',
  49. path: '/foo.html?json=%22%5C%22foo%5C%22%22',
  50. hash: '#h%5Ca%5Cs%5Ch',
  51. href: 'http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch'
  52. },
  53. 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg': {
  54. protocol: 'http:',
  55. slashes: true,
  56. host: 'evil-phisher',
  57. hostname: 'evil-phisher',
  58. pathname: '/foo.html',
  59. path: '/foo.html',
  60. hash: '#h%5Ca%5Cs%5Ch?blarg',
  61. href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg'
  62. },
  63. 'http:\\\\evil-phisher\\foo.html': {
  64. protocol: 'http:',
  65. slashes: true,
  66. host: 'evil-phisher',
  67. hostname: 'evil-phisher',
  68. pathname: '/foo.html',
  69. path: '/foo.html',
  70. href: 'http://evil-phisher/foo.html'
  71. },
  72. 'HTTP://www.example.com/' : {
  73. 'href': 'http://www.example.com/',
  74. 'protocol': 'http:',
  75. 'slashes': true,
  76. 'host': 'www.example.com',
  77. 'hostname': 'www.example.com',
  78. 'pathname': '/',
  79. 'path': '/'
  80. },
  81. 'HTTP://www.example.com' : {
  82. 'href': 'http://www.example.com/',
  83. 'protocol': 'http:',
  84. 'slashes': true,
  85. 'host': 'www.example.com',
  86. 'hostname': 'www.example.com',
  87. 'pathname': '/',
  88. 'path': '/'
  89. },
  90. 'http://www.ExAmPlE.com/' : {
  91. 'href': 'http://www.example.com/',
  92. 'protocol': 'http:',
  93. 'slashes': true,
  94. 'host': 'www.example.com',
  95. 'hostname': 'www.example.com',
  96. 'pathname': '/',
  97. 'path': '/'
  98. },
  99. 'http://user:pw@www.ExAmPlE.com/' : {
  100. 'href': 'http://user:pw@www.example.com/',
  101. 'protocol': 'http:',
  102. 'slashes': true,
  103. 'auth': 'user:pw',
  104. 'host': 'www.example.com',
  105. 'hostname': 'www.example.com',
  106. 'pathname': '/',
  107. 'path': '/'
  108. },
  109. 'http://USER:PW@www.ExAmPlE.com/' : {
  110. 'href': 'http://USER:PW@www.example.com/',
  111. 'protocol': 'http:',
  112. 'slashes': true,
  113. 'auth': 'USER:PW',
  114. 'host': 'www.example.com',
  115. 'hostname': 'www.example.com',
  116. 'pathname': '/',
  117. 'path': '/'
  118. },
  119. 'http://user@www.example.com/' : {
  120. 'href': 'http://user@www.example.com/',
  121. 'protocol': 'http:',
  122. 'slashes': true,
  123. 'auth': 'user',
  124. 'host': 'www.example.com',
  125. 'hostname': 'www.example.com',
  126. 'pathname': '/',
  127. 'path': '/'
  128. },
  129. 'http://user%3Apw@www.example.com/' : {
  130. 'href': 'http://user:pw@www.example.com/',
  131. 'protocol': 'http:',
  132. 'slashes': true,
  133. 'auth': 'user:pw',
  134. 'host': 'www.example.com',
  135. 'hostname': 'www.example.com',
  136. 'pathname': '/',
  137. 'path': '/'
  138. },
  139. 'http://x.com/path?that\'s#all, folks' : {
  140. 'href': 'http://x.com/path?that%27s#all,%20folks',
  141. 'protocol': 'http:',
  142. 'slashes': true,
  143. 'host': 'x.com',
  144. 'hostname': 'x.com',
  145. 'search': '?that%27s',
  146. 'query': 'that%27s',
  147. 'pathname': '/path',
  148. 'hash': '#all,%20folks',
  149. 'path': '/path?that%27s'
  150. },
  151. 'HTTP://X.COM/Y' : {
  152. 'href': 'http://x.com/Y',
  153. 'protocol': 'http:',
  154. 'slashes': true,
  155. 'host': 'x.com',
  156. 'hostname': 'x.com',
  157. 'pathname': '/Y',
  158. 'path': '/Y'
  159. },
  160. // + not an invalid host character
  161. // per https://url.spec.whatwg.org/#host-parsing
  162. 'http://x.y.com+a/b/c' : {
  163. 'href': 'http://x.y.com+a/b/c',
  164. 'protocol': 'http:',
  165. 'slashes': true,
  166. 'host': 'x.y.com+a',
  167. 'hostname': 'x.y.com+a',
  168. 'pathname': '/b/c',
  169. 'path': '/b/c'
  170. },
  171. // an unexpected invalid char in the hostname.
  172. 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i' : {
  173. 'href': 'http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei',
  174. 'protocol': 'http:',
  175. 'slashes': true,
  176. 'host': 'x.y.com',
  177. 'hostname': 'x.y.com',
  178. 'pathname': ';a/b/c',
  179. 'search': '?d=e',
  180. 'query': 'd=e',
  181. 'hash': '#f%20g%3Ch%3Ei',
  182. 'path': ';a/b/c?d=e'
  183. },
  184. // make sure that we don't accidentally lcast the path parts.
  185. 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i' : {
  186. 'href': 'http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
  187. 'protocol': 'http:',
  188. 'slashes': true,
  189. 'host': 'x.y.com',
  190. 'hostname': 'x.y.com',
  191. 'pathname': ';A/b/c',
  192. 'search': '?d=e',
  193. 'query': 'd=e',
  194. 'hash': '#f%20g%3Ch%3Ei',
  195. 'path': ';A/b/c?d=e'
  196. },
  197. 'http://x...y...#p': {
  198. 'href': 'http://x...y.../#p',
  199. 'protocol': 'http:',
  200. 'slashes': true,
  201. 'host': 'x...y...',
  202. 'hostname': 'x...y...',
  203. 'hash': '#p',
  204. 'pathname': '/',
  205. 'path': '/'
  206. },
  207. 'http://x/p/"quoted"': {
  208. 'href': 'http://x/p/%22quoted%22',
  209. 'protocol': 'http:',
  210. 'slashes': true,
  211. 'host': 'x',
  212. 'hostname': 'x',
  213. 'pathname': '/p/%22quoted%22',
  214. 'path': '/p/%22quoted%22'
  215. },
  216. '<http://goo.corn/bread> Is a URL!': {
  217. 'href': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
  218. 'pathname': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
  219. 'path': '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!'
  220. },
  221. 'http://www.narwhaljs.org/blog/categories?id=news' : {
  222. 'href': 'http://www.narwhaljs.org/blog/categories?id=news',
  223. 'protocol': 'http:',
  224. 'slashes': true,
  225. 'host': 'www.narwhaljs.org',
  226. 'hostname': 'www.narwhaljs.org',
  227. 'search': '?id=news',
  228. 'query': 'id=news',
  229. 'pathname': '/blog/categories',
  230. 'path': '/blog/categories?id=news'
  231. },
  232. 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=' : {
  233. 'href': 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
  234. 'protocol': 'http:',
  235. 'slashes': true,
  236. 'host': 'mt0.google.com',
  237. 'hostname': 'mt0.google.com',
  238. 'pathname': '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
  239. 'path': '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
  240. },
  241. 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=' : {
  242. 'href': 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api' +
  243. '&x=2&y=2&z=3&s=',
  244. 'protocol': 'http:',
  245. 'slashes': true,
  246. 'host': 'mt0.google.com',
  247. 'hostname': 'mt0.google.com',
  248. 'search': '???&hl=en&src=api&x=2&y=2&z=3&s=',
  249. 'query': '??&hl=en&src=api&x=2&y=2&z=3&s=',
  250. 'pathname': '/vt/lyrs=m@114',
  251. 'path': '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
  252. },
  253. 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=':
  254. {
  255. 'href': 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' +
  256. '&hl=en&src=api&x=2&y=2&z=3&s=',
  257. 'protocol': 'http:',
  258. 'slashes': true,
  259. 'host': 'mt0.google.com',
  260. 'auth': 'user:pass',
  261. 'hostname': 'mt0.google.com',
  262. 'search': '???&hl=en&src=api&x=2&y=2&z=3&s=',
  263. 'query': '??&hl=en&src=api&x=2&y=2&z=3&s=',
  264. 'pathname': '/vt/lyrs=m@114',
  265. 'path': '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
  266. },
  267. 'file:///etc/passwd' : {
  268. 'href': 'file:///etc/passwd',
  269. 'slashes': true,
  270. 'protocol': 'file:',
  271. 'pathname': '/etc/passwd',
  272. 'hostname': '',
  273. 'host': '',
  274. 'path': '/etc/passwd'
  275. },
  276. 'file://localhost/etc/passwd' : {
  277. 'href': 'file://localhost/etc/passwd',
  278. 'protocol': 'file:',
  279. 'slashes': true,
  280. 'pathname': '/etc/passwd',
  281. 'hostname': 'localhost',
  282. 'host': 'localhost',
  283. 'path': '/etc/passwd'
  284. },
  285. 'file://foo/etc/passwd' : {
  286. 'href': 'file://foo/etc/passwd',
  287. 'protocol': 'file:',
  288. 'slashes': true,
  289. 'pathname': '/etc/passwd',
  290. 'hostname': 'foo',
  291. 'host': 'foo',
  292. 'path': '/etc/passwd'
  293. },
  294. 'file:///etc/node/' : {
  295. 'href': 'file:///etc/node/',
  296. 'slashes': true,
  297. 'protocol': 'file:',
  298. 'pathname': '/etc/node/',
  299. 'hostname': '',
  300. 'host': '',
  301. 'path': '/etc/node/'
  302. },
  303. 'file://localhost/etc/node/' : {
  304. 'href': 'file://localhost/etc/node/',
  305. 'protocol': 'file:',
  306. 'slashes': true,
  307. 'pathname': '/etc/node/',
  308. 'hostname': 'localhost',
  309. 'host': 'localhost',
  310. 'path': '/etc/node/'
  311. },
  312. 'file://foo/etc/node/' : {
  313. 'href': 'file://foo/etc/node/',
  314. 'protocol': 'file:',
  315. 'slashes': true,
  316. 'pathname': '/etc/node/',
  317. 'hostname': 'foo',
  318. 'host': 'foo',
  319. 'path': '/etc/node/'
  320. },
  321. 'http:/baz/../foo/bar' : {
  322. 'href': 'http:/baz/../foo/bar',
  323. 'protocol': 'http:',
  324. 'pathname': '/baz/../foo/bar',
  325. 'path': '/baz/../foo/bar'
  326. },
  327. 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag' : {
  328. 'href': 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag',
  329. 'protocol': 'http:',
  330. 'slashes': true,
  331. 'host': 'example.com:8000',
  332. 'auth': 'user:pass',
  333. 'port': '8000',
  334. 'hostname': 'example.com',
  335. 'hash': '#frag',
  336. 'search': '?baz=quux',
  337. 'query': 'baz=quux',
  338. 'pathname': '/foo/bar',
  339. 'path': '/foo/bar?baz=quux'
  340. },
  341. '//user:pass@example.com:8000/foo/bar?baz=quux#frag' : {
  342. 'href': '//user:pass@example.com:8000/foo/bar?baz=quux#frag',
  343. 'slashes': true,
  344. 'host': 'example.com:8000',
  345. 'auth': 'user:pass',
  346. 'port': '8000',
  347. 'hostname': 'example.com',
  348. 'hash': '#frag',
  349. 'search': '?baz=quux',
  350. 'query': 'baz=quux',
  351. 'pathname': '/foo/bar',
  352. 'path': '/foo/bar?baz=quux'
  353. },
  354. '/foo/bar?baz=quux#frag' : {
  355. 'href': '/foo/bar?baz=quux#frag',
  356. 'hash': '#frag',
  357. 'search': '?baz=quux',
  358. 'query': 'baz=quux',
  359. 'pathname': '/foo/bar',
  360. 'path': '/foo/bar?baz=quux'
  361. },
  362. 'http:/foo/bar?baz=quux#frag' : {
  363. 'href': 'http:/foo/bar?baz=quux#frag',
  364. 'protocol': 'http:',
  365. 'hash': '#frag',
  366. 'search': '?baz=quux',
  367. 'query': 'baz=quux',
  368. 'pathname': '/foo/bar',
  369. 'path': '/foo/bar?baz=quux'
  370. },
  371. 'mailto:foo@bar.com?subject=hello' : {
  372. 'href': 'mailto:foo@bar.com?subject=hello',
  373. 'protocol': 'mailto:',
  374. 'host': 'bar.com',
  375. 'auth' : 'foo',
  376. 'hostname' : 'bar.com',
  377. 'search': '?subject=hello',
  378. 'query': 'subject=hello',
  379. 'path': '?subject=hello'
  380. },
  381. 'javascript:alert(\'hello\');' : {
  382. 'href': 'javascript:alert(\'hello\');',
  383. 'protocol': 'javascript:',
  384. 'pathname': 'alert(\'hello\');',
  385. 'path': 'alert(\'hello\');'
  386. },
  387. 'xmpp:isaacschlueter@jabber.org' : {
  388. 'href': 'xmpp:isaacschlueter@jabber.org',
  389. 'protocol': 'xmpp:',
  390. 'host': 'jabber.org',
  391. 'auth': 'isaacschlueter',
  392. 'hostname': 'jabber.org'
  393. },
  394. 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar' : {
  395. 'href' : 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar',
  396. 'protocol' : 'http:',
  397. 'slashes': true,
  398. 'host' : '127.0.0.1:8080',
  399. 'auth' : 'atpass:foo@bar',
  400. 'hostname' : '127.0.0.1',
  401. 'port' : '8080',
  402. 'pathname': '/path',
  403. 'search' : '?search=foo',
  404. 'query' : 'search=foo',
  405. 'hash' : '#bar',
  406. 'path': '/path?search=foo'
  407. },
  408. 'svn+ssh://foo/bar': {
  409. 'href': 'svn+ssh://foo/bar',
  410. 'host': 'foo',
  411. 'hostname': 'foo',
  412. 'protocol': 'svn+ssh:',
  413. 'pathname': '/bar',
  414. 'path': '/bar',
  415. 'slashes': true
  416. },
  417. 'dash-test://foo/bar': {
  418. 'href': 'dash-test://foo/bar',
  419. 'host': 'foo',
  420. 'hostname': 'foo',
  421. 'protocol': 'dash-test:',
  422. 'pathname': '/bar',
  423. 'path': '/bar',
  424. 'slashes': true
  425. },
  426. 'dash-test:foo/bar': {
  427. 'href': 'dash-test:foo/bar',
  428. 'host': 'foo',
  429. 'hostname': 'foo',
  430. 'protocol': 'dash-test:',
  431. 'pathname': '/bar',
  432. 'path': '/bar'
  433. },
  434. 'dot.test://foo/bar': {
  435. 'href': 'dot.test://foo/bar',
  436. 'host': 'foo',
  437. 'hostname': 'foo',
  438. 'protocol': 'dot.test:',
  439. 'pathname': '/bar',
  440. 'path': '/bar',
  441. 'slashes': true
  442. },
  443. 'dot.test:foo/bar': {
  444. 'href': 'dot.test:foo/bar',
  445. 'host': 'foo',
  446. 'hostname': 'foo',
  447. 'protocol': 'dot.test:',
  448. 'pathname': '/bar',
  449. 'path': '/bar'
  450. },
  451. // IDNA tests
  452. 'http://www.日本語.com/' : {
  453. 'href': 'http://www.xn--wgv71a119e.com/',
  454. 'protocol': 'http:',
  455. 'slashes': true,
  456. 'host': 'www.xn--wgv71a119e.com',
  457. 'hostname': 'www.xn--wgv71a119e.com',
  458. 'pathname': '/',
  459. 'path': '/'
  460. },
  461. 'http://example.Bücher.com/' : {
  462. 'href': 'http://example.xn--bcher-kva.com/',
  463. 'protocol': 'http:',
  464. 'slashes': true,
  465. 'host': 'example.xn--bcher-kva.com',
  466. 'hostname': 'example.xn--bcher-kva.com',
  467. 'pathname': '/',
  468. 'path': '/'
  469. },
  470. 'http://www.Äffchen.com/' : {
  471. 'href': 'http://www.xn--ffchen-9ta.com/',
  472. 'protocol': 'http:',
  473. 'slashes': true,
  474. 'host': 'www.xn--ffchen-9ta.com',
  475. 'hostname': 'www.xn--ffchen-9ta.com',
  476. 'pathname': '/',
  477. 'path': '/'
  478. },
  479. 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i' : {
  480. 'href': 'http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
  481. 'protocol': 'http:',
  482. 'slashes': true,
  483. 'host': 'www.xn--ffchen-9ta.com',
  484. 'hostname': 'www.xn--ffchen-9ta.com',
  485. 'pathname': ';A/b/c',
  486. 'search': '?d=e',
  487. 'query': 'd=e',
  488. 'hash': '#f%20g%3Ch%3Ei',
  489. 'path': ';A/b/c?d=e'
  490. },
  491. 'http://SÉLIER.COM/' : {
  492. 'href': 'http://xn--slier-bsa.com/',
  493. 'protocol': 'http:',
  494. 'slashes': true,
  495. 'host': 'xn--slier-bsa.com',
  496. 'hostname': 'xn--slier-bsa.com',
  497. 'pathname': '/',
  498. 'path': '/'
  499. },
  500. 'http://ليهمابتكلموشعربي؟.ي؟/' : {
  501. 'href': 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/',
  502. 'protocol': 'http:',
  503. 'slashes': true,
  504. 'host': 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
  505. 'hostname': 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
  506. 'pathname': '/',
  507. 'path': '/'
  508. },
  509. 'http://➡.ws/➡' : {
  510. 'href': 'http://xn--hgi.ws/➡',
  511. 'protocol': 'http:',
  512. 'slashes': true,
  513. 'host': 'xn--hgi.ws',
  514. 'hostname': 'xn--hgi.ws',
  515. 'pathname': '/➡',
  516. 'path': '/➡'
  517. },
  518. 'http://bucket_name.s3.amazonaws.com/image.jpg': {
  519. protocol: 'http:',
  520. 'slashes': true,
  521. slashes: true,
  522. host: 'bucket_name.s3.amazonaws.com',
  523. hostname: 'bucket_name.s3.amazonaws.com',
  524. pathname: '/image.jpg',
  525. href: 'http://bucket_name.s3.amazonaws.com/image.jpg',
  526. 'path': '/image.jpg'
  527. },
  528. 'git+http://github.com/joyent/node.git': {
  529. protocol: 'git+http:',
  530. slashes: true,
  531. host: 'github.com',
  532. hostname: 'github.com',
  533. pathname: '/joyent/node.git',
  534. path: '/joyent/node.git',
  535. href: 'git+http://github.com/joyent/node.git'
  536. },
  537. //if local1@domain1 is uses as a relative URL it may
  538. //be parse into auth@hostname, but here there is no
  539. //way to make it work in url.parse, I add the test to be explicit
  540. 'local1@domain1': {
  541. 'pathname': 'local1@domain1',
  542. 'path': 'local1@domain1',
  543. 'href': 'local1@domain1'
  544. },
  545. //While this may seem counter-intuitive, a browser will parse
  546. //<a href='www.google.com'> as a path.
  547. 'www.example.com' : {
  548. 'href': 'www.example.com',
  549. 'pathname': 'www.example.com',
  550. 'path': 'www.example.com'
  551. },
  552. // ipv6 support
  553. '[fe80::1]': {
  554. 'href': '[fe80::1]',
  555. 'pathname': '[fe80::1]',
  556. 'path': '[fe80::1]'
  557. },
  558. 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': {
  559. 'protocol': 'coap:',
  560. 'slashes': true,
  561. 'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]',
  562. 'hostname': 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
  563. 'href': 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/',
  564. 'pathname': '/',
  565. 'path': '/'
  566. },
  567. 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': {
  568. 'protocol': 'coap:',
  569. 'slashes': true,
  570. 'host': '[1080:0:0:0:8:800:200c:417a]:61616',
  571. 'port': '61616',
  572. 'hostname': '1080:0:0:0:8:800:200c:417a',
  573. 'href': 'coap://[1080:0:0:0:8:800:200c:417a]:61616/',
  574. 'pathname': '/',
  575. 'path': '/'
  576. },
  577. 'http://user:password@[3ffe:2a00:100:7031::1]:8080': {
  578. 'protocol': 'http:',
  579. 'slashes': true,
  580. 'auth': 'user:password',
  581. 'host': '[3ffe:2a00:100:7031::1]:8080',
  582. 'port': '8080',
  583. 'hostname': '3ffe:2a00:100:7031::1',
  584. 'href': 'http://user:password@[3ffe:2a00:100:7031::1]:8080/',
  585. 'pathname': '/',
  586. 'path': '/'
  587. },
  588. 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': {
  589. 'protocol': 'coap:',
  590. 'slashes': true,
  591. 'auth': 'u:p',
  592. 'host': '[::192.9.5.5]:61616',
  593. 'port': '61616',
  594. 'hostname': '::192.9.5.5',
  595. 'href': 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature',
  596. 'search': '?n=Temperature',
  597. 'query': 'n=Temperature',
  598. 'pathname': '/.well-known/r',
  599. 'path': '/.well-known/r?n=Temperature'
  600. },
  601. // empty port
  602. 'http://example.com:': {
  603. 'protocol': 'http:',
  604. 'slashes': true,
  605. 'host': 'example.com',
  606. 'hostname': 'example.com',
  607. 'href': 'http://example.com/',
  608. 'pathname': '/',
  609. 'path': '/'
  610. },
  611. 'http://example.com:/a/b.html': {
  612. 'protocol': 'http:',
  613. 'slashes': true,
  614. 'host': 'example.com',
  615. 'hostname': 'example.com',
  616. 'href': 'http://example.com/a/b.html',
  617. 'pathname': '/a/b.html',
  618. 'path': '/a/b.html'
  619. },
  620. 'http://example.com:?a=b': {
  621. 'protocol': 'http:',
  622. 'slashes': true,
  623. 'host': 'example.com',
  624. 'hostname': 'example.com',
  625. 'href': 'http://example.com/?a=b',
  626. 'search': '?a=b',
  627. 'query': 'a=b',
  628. 'pathname': '/',
  629. 'path': '/?a=b'
  630. },
  631. 'http://example.com:#abc': {
  632. 'protocol': 'http:',
  633. 'slashes': true,
  634. 'host': 'example.com',
  635. 'hostname': 'example.com',
  636. 'href': 'http://example.com/#abc',
  637. 'hash': '#abc',
  638. 'pathname': '/',
  639. 'path': '/'
  640. },
  641. 'http://[fe80::1]:/a/b?a=b#abc': {
  642. 'protocol': 'http:',
  643. 'slashes': true,
  644. 'host': '[fe80::1]',
  645. 'hostname': 'fe80::1',
  646. 'href': 'http://[fe80::1]/a/b?a=b#abc',
  647. 'search': '?a=b',
  648. 'query': 'a=b',
  649. 'hash': '#abc',
  650. 'pathname': '/a/b',
  651. 'path': '/a/b?a=b'
  652. },
  653. 'http://-lovemonsterz.tumblr.com/rss': {
  654. 'protocol': 'http:',
  655. 'slashes': true,
  656. 'host': '-lovemonsterz.tumblr.com',
  657. 'hostname': '-lovemonsterz.tumblr.com',
  658. 'href': 'http://-lovemonsterz.tumblr.com/rss',
  659. 'pathname': '/rss',
  660. 'path': '/rss',
  661. },
  662. 'http://-lovemonsterz.tumblr.com:80/rss': {
  663. 'protocol': 'http:',
  664. 'slashes': true,
  665. 'port': '80',
  666. 'host': '-lovemonsterz.tumblr.com:80',
  667. 'hostname': '-lovemonsterz.tumblr.com',
  668. 'href': 'http://-lovemonsterz.tumblr.com:80/rss',
  669. 'pathname': '/rss',
  670. 'path': '/rss',
  671. },
  672. 'http://user:pass@-lovemonsterz.tumblr.com/rss': {
  673. 'protocol': 'http:',
  674. 'slashes': true,
  675. 'auth': 'user:pass',
  676. 'host': '-lovemonsterz.tumblr.com',
  677. 'hostname': '-lovemonsterz.tumblr.com',
  678. 'href': 'http://user:pass@-lovemonsterz.tumblr.com/rss',
  679. 'pathname': '/rss',
  680. 'path': '/rss',
  681. },
  682. 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': {
  683. 'protocol': 'http:',
  684. 'slashes': true,
  685. 'auth': 'user:pass',
  686. 'port': '80',
  687. 'host': '-lovemonsterz.tumblr.com:80',
  688. 'hostname': '-lovemonsterz.tumblr.com',
  689. 'href': 'http://user:pass@-lovemonsterz.tumblr.com:80/rss',
  690. 'pathname': '/rss',
  691. 'path': '/rss',
  692. },
  693. 'http://_jabber._tcp.google.com/test': {
  694. 'protocol': 'http:',
  695. 'slashes': true,
  696. 'host': '_jabber._tcp.google.com',
  697. 'hostname': '_jabber._tcp.google.com',
  698. 'href': 'http://_jabber._tcp.google.com/test',
  699. 'pathname': '/test',
  700. 'path': '/test',
  701. },
  702. 'http://user:pass@_jabber._tcp.google.com/test': {
  703. 'protocol': 'http:',
  704. 'slashes': true,
  705. 'auth': 'user:pass',
  706. 'host': '_jabber._tcp.google.com',
  707. 'hostname': '_jabber._tcp.google.com',
  708. 'href': 'http://user:pass@_jabber._tcp.google.com/test',
  709. 'pathname': '/test',
  710. 'path': '/test',
  711. },
  712. 'http://_jabber._tcp.google.com:80/test': {
  713. 'protocol': 'http:',
  714. 'slashes': true,
  715. 'port': '80',
  716. 'host': '_jabber._tcp.google.com:80',
  717. 'hostname': '_jabber._tcp.google.com',
  718. 'href': 'http://_jabber._tcp.google.com:80/test',
  719. 'pathname': '/test',
  720. 'path': '/test',
  721. },
  722. 'http://user:pass@_jabber._tcp.google.com:80/test': {
  723. 'protocol': 'http:',
  724. 'slashes': true,
  725. 'auth': 'user:pass',
  726. 'port': '80',
  727. 'host': '_jabber._tcp.google.com:80',
  728. 'hostname': '_jabber._tcp.google.com',
  729. 'href': 'http://user:pass@_jabber._tcp.google.com:80/test',
  730. 'pathname': '/test',
  731. 'path': '/test',
  732. },
  733. 'http://x:1/\' <>"`/{}|\\^~`/': {
  734. protocol: 'http:',
  735. slashes: true,
  736. host: 'x:1',
  737. port: '1',
  738. hostname: 'x',
  739. pathname: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
  740. path: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
  741. href: 'http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/'
  742. },
  743. 'http://a@b@c/': {
  744. protocol: 'http:',
  745. slashes: true,
  746. auth: 'a@b',
  747. host: 'c',
  748. hostname: 'c',
  749. href: 'http://a%40b@c/',
  750. path: '/',
  751. pathname: '/'
  752. },
  753. 'http://a@b?@c': {
  754. protocol: 'http:',
  755. slashes: true,
  756. auth: 'a',
  757. host: 'b',
  758. hostname: 'b',
  759. href: 'http://a@b/?@c',
  760. path: '/?@c',
  761. pathname: '/',
  762. search: '?@c',
  763. query: '@c'
  764. },
  765. 'http://a\r" \t\n<\'b:b@c\r\nd/e?f':{
  766. protocol: 'http:',
  767. slashes: true,
  768. auth: 'a\r" \t\n<\'b:b',
  769. host: 'c',
  770. port: null,
  771. hostname: 'c',
  772. hash: null,
  773. search: '?f',
  774. query: 'f',
  775. pathname: '%0D%0Ad/e',
  776. path: '%0D%0Ad/e?f',
  777. href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f'
  778. },
  779. // git urls used by npm
  780. 'git+ssh://git@github.com:npm/npm': {
  781. protocol: 'git+ssh:',
  782. slashes: true,
  783. auth: 'git',
  784. host: 'github.com',
  785. port: null,
  786. hostname: 'github.com',
  787. hash: null,
  788. search: null,
  789. query: null,
  790. pathname: '/:npm/npm',
  791. path: '/:npm/npm',
  792. href: 'git+ssh://git@github.com/:npm/npm'
  793. }
  794. };
  795. Object.keys(parseTests).forEach(function(u) {
  796. test('parse(' + u + ')', function() {
  797. var actual = url.parse(u),
  798. spaced = url.parse(' \t ' + u + '\n\t');
  799. expected = parseTests[u];
  800. Object.keys(actual).forEach(function (i) {
  801. if (expected[i] === undefined && actual[i] === null) {
  802. expected[i] = null;
  803. }
  804. });
  805. assert.deepEqual(actual, expected);
  806. assert.deepEqual(spaced, expected);
  807. var expected = parseTests[u].href,
  808. actual = url.format(parseTests[u]);
  809. assert.equal(actual, expected,
  810. 'format(' + u + ') == ' + u + '\nactual:' + actual);
  811. });
  812. });
  813. var parseTestsWithQueryString = {
  814. '/foo/bar?baz=quux#frag' : {
  815. 'href': '/foo/bar?baz=quux#frag',
  816. 'hash': '#frag',
  817. 'search': '?baz=quux',
  818. 'query': {
  819. 'baz': 'quux'
  820. },
  821. 'pathname': '/foo/bar',
  822. 'path': '/foo/bar?baz=quux'
  823. },
  824. 'http://example.com' : {
  825. 'href': 'http://example.com/',
  826. 'protocol': 'http:',
  827. 'slashes': true,
  828. 'host': 'example.com',
  829. 'hostname': 'example.com',
  830. 'query': {},
  831. 'search': '',
  832. 'pathname': '/',
  833. 'path': '/'
  834. },
  835. '/example': {
  836. protocol: null,
  837. slashes: null,
  838. auth: null,
  839. host: null,
  840. port: null,
  841. hostname: null,
  842. hash: null,
  843. search: '',
  844. query: {},
  845. pathname: '/example',
  846. path: '/example',
  847. href: '/example'
  848. },
  849. '/example?query=value':{
  850. protocol: null,
  851. slashes: null,
  852. auth: null,
  853. host: null,
  854. port: null,
  855. hostname: null,
  856. hash: null,
  857. search: '?query=value',
  858. query: { query: 'value' },
  859. pathname: '/example',
  860. path: '/example?query=value',
  861. href: '/example?query=value'
  862. }
  863. };
  864. Object.keys(parseTestsWithQueryString).forEach(function(u) {
  865. test('parse(' + u + ')', function() {
  866. var actual = url.parse(u, true);
  867. var expected = parseTestsWithQueryString[u];
  868. for (var i in actual) {
  869. if (actual[i] === null && expected[i] === undefined) {
  870. expected[i] = null;
  871. }
  872. }
  873. assert.deepEqual(actual, expected);
  874. });
  875. });
  876. // some extra formatting tests, just to verify
  877. // that it'll format slightly wonky content to a valid url.
  878. var formatTests = {
  879. 'http://example.com?' : {
  880. 'href': 'http://example.com/?',
  881. 'protocol': 'http:',
  882. 'slashes': true,
  883. 'host': 'example.com',
  884. 'hostname': 'example.com',
  885. 'search': '?',
  886. 'query': {},
  887. 'pathname': '/'
  888. },
  889. 'http://example.com?foo=bar#frag' : {
  890. 'href': 'http://example.com/?foo=bar#frag',
  891. 'protocol': 'http:',
  892. 'host': 'example.com',
  893. 'hostname': 'example.com',
  894. 'hash': '#frag',
  895. 'search': '?foo=bar',
  896. 'query': 'foo=bar',
  897. 'pathname': '/'
  898. },
  899. 'http://example.com?foo=@bar#frag' : {
  900. 'href': 'http://example.com/?foo=@bar#frag',
  901. 'protocol': 'http:',
  902. 'host': 'example.com',
  903. 'hostname': 'example.com',
  904. 'hash': '#frag',
  905. 'search': '?foo=@bar',
  906. 'query': 'foo=@bar',
  907. 'pathname': '/'
  908. },
  909. 'http://example.com?foo=/bar/#frag' : {
  910. 'href': 'http://example.com/?foo=/bar/#frag',
  911. 'protocol': 'http:',
  912. 'host': 'example.com',
  913. 'hostname': 'example.com',
  914. 'hash': '#frag',
  915. 'search': '?foo=/bar/',
  916. 'query': 'foo=/bar/',
  917. 'pathname': '/'
  918. },
  919. 'http://example.com?foo=?bar/#frag' : {
  920. 'href': 'http://example.com/?foo=?bar/#frag',
  921. 'protocol': 'http:',
  922. 'host': 'example.com',
  923. 'hostname': 'example.com',
  924. 'hash': '#frag',
  925. 'search': '?foo=?bar/',
  926. 'query': 'foo=?bar/',
  927. 'pathname': '/'
  928. },
  929. 'http://example.com#frag=?bar/#frag' : {
  930. 'href': 'http://example.com/#frag=?bar/#frag',
  931. 'protocol': 'http:',
  932. 'host': 'example.com',
  933. 'hostname': 'example.com',
  934. 'hash': '#frag=?bar/#frag',
  935. 'pathname': '/'
  936. },
  937. 'http://google.com" onload="alert(42)/' : {
  938. 'href': 'http://google.com/%22%20onload=%22alert(42)/',
  939. 'protocol': 'http:',
  940. 'host': 'google.com',
  941. 'pathname': '/%22%20onload=%22alert(42)/'
  942. },
  943. 'http://a.com/a/b/c?s#h' : {
  944. 'href': 'http://a.com/a/b/c?s#h',
  945. 'protocol': 'http',
  946. 'host': 'a.com',
  947. 'pathname': 'a/b/c',
  948. 'hash': 'h',
  949. 'search': 's'
  950. },
  951. 'xmpp:isaacschlueter@jabber.org' : {
  952. 'href': 'xmpp:isaacschlueter@jabber.org',
  953. 'protocol': 'xmpp:',
  954. 'host': 'jabber.org',
  955. 'auth': 'isaacschlueter',
  956. 'hostname': 'jabber.org'
  957. },
  958. 'http://atpass:foo%40bar@127.0.0.1/' : {
  959. 'href': 'http://atpass:foo%40bar@127.0.0.1/',
  960. 'auth': 'atpass:foo@bar',
  961. 'hostname': '127.0.0.1',
  962. 'protocol': 'http:',
  963. 'pathname': '/'
  964. },
  965. 'http://atslash%2F%40:%2F%40@foo/' : {
  966. 'href': 'http://atslash%2F%40:%2F%40@foo/',
  967. 'auth': 'atslash/@:/@',
  968. 'hostname': 'foo',
  969. 'protocol': 'http:',
  970. 'pathname': '/'
  971. },
  972. 'svn+ssh://foo/bar': {
  973. 'href': 'svn+ssh://foo/bar',
  974. 'hostname': 'foo',
  975. 'protocol': 'svn+ssh:',
  976. 'pathname': '/bar',
  977. 'slashes': true
  978. },
  979. 'dash-test://foo/bar': {
  980. 'href': 'dash-test://foo/bar',
  981. 'hostname': 'foo',
  982. 'protocol': 'dash-test:',
  983. 'pathname': '/bar',
  984. 'slashes': true
  985. },
  986. 'dash-test:foo/bar': {
  987. 'href': 'dash-test:foo/bar',
  988. 'hostname': 'foo',
  989. 'protocol': 'dash-test:',
  990. 'pathname': '/bar'
  991. },
  992. 'dot.test://foo/bar': {
  993. 'href': 'dot.test://foo/bar',
  994. 'hostname': 'foo',
  995. 'protocol': 'dot.test:',
  996. 'pathname': '/bar',
  997. 'slashes': true
  998. },
  999. 'dot.test:foo/bar': {
  1000. 'href': 'dot.test:foo/bar',
  1001. 'hostname': 'foo',
  1002. 'protocol': 'dot.test:',
  1003. 'pathname': '/bar'
  1004. },
  1005. // ipv6 support
  1006. 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
  1007. 'href': 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
  1008. 'protocol': 'coap:',
  1009. 'auth': 'u:p',
  1010. 'hostname': '::1',
  1011. 'port': '61616',
  1012. 'pathname': '/.well-known/r',
  1013. 'search': 'n=Temperature'
  1014. },
  1015. 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
  1016. 'href': 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
  1017. 'protocol': 'coap',
  1018. 'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
  1019. 'pathname': '/s/stopButton'
  1020. },
  1021. // encode context-specific delimiters in path and query, but do not touch
  1022. // other non-delimiter chars like `%`.
  1023. // <https://github.com/joyent/node/issues/4082>
  1024. // `#`,`?` in path
  1025. '/path/to/%%23%3F+=&.txt?foo=theA1#bar' : {
  1026. href : '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
  1027. pathname: '/path/to/%#?+=&.txt',
  1028. query: {
  1029. foo: 'theA1'
  1030. },
  1031. hash: "#bar"
  1032. },
  1033. // `#`,`?` in path + `#` in query
  1034. '/path/to/%%23%3F+=&.txt?foo=the%231#bar' : {
  1035. href : '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
  1036. pathname: '/path/to/%#?+=&.txt',
  1037. query: {
  1038. foo: 'the#1'
  1039. },
  1040. hash: "#bar"
  1041. },
  1042. // `?` and `#` in path and search
  1043. 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
  1044. href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
  1045. protocol: 'http:',
  1046. hostname: 'ex.com',
  1047. hash: '#frag',
  1048. search: '?abc=the#1?&foo=bar',
  1049. pathname: '/foo?100%m#r',
  1050. },
  1051. // `?` and `#` in search only
  1052. 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
  1053. href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
  1054. protocol: 'http:',
  1055. hostname: 'ex.com',
  1056. hash: '#frag',
  1057. search: '?abc=the#1?&foo=bar',
  1058. pathname: '/fooA100%mBr',
  1059. }
  1060. };
  1061. Object.keys(formatTests).forEach(function(u) {
  1062. test('format(' + u + ')', function() {
  1063. var expect = formatTests[u].href;
  1064. delete formatTests[u].href;
  1065. var actual = url.format(u);
  1066. var actualObj = url.format(formatTests[u]);
  1067. assert.equal(actual, expect,
  1068. 'wonky format(' + u + ') == ' + expect +
  1069. '\nactual:' + actual);
  1070. assert.equal(actualObj, expect,
  1071. 'wonky format(' + JSON.stringify(formatTests[u]) +
  1072. ') == ' + expect +
  1073. '\nactual: ' + actualObj);
  1074. });
  1075. });
  1076. /*
  1077. [from, path, expected]
  1078. */
  1079. var relativeTests = [
  1080. ['/foo/bar/baz', 'quux', '/foo/bar/quux'],
  1081. ['/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'],
  1082. ['/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'],
  1083. ['/foo/bar/baz', '../quux/baz', '/foo/quux/baz'],
  1084. ['/foo/bar/baz', '/bar', '/bar'],
  1085. ['/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'],
  1086. ['/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'],
  1087. ['/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'],
  1088. ['/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'],
  1089. ['/foo', '.', '/'],
  1090. ['/foo', '..', '/'],
  1091. ['/foo/', '.', '/foo/'],
  1092. ['/foo/', '..', '/'],
  1093. ['/foo/bar', '.', '/foo/'],
  1094. ['/foo/bar', '..', '/'],
  1095. ['/foo/bar/', '.', '/foo/bar/'],
  1096. ['/foo/bar/', '..', '/foo/'],
  1097. ['foo/bar', '../../../baz', '../../baz'],
  1098. ['foo/bar/', '../../../baz', '../baz'],
  1099. ['http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'],
  1100. ['http://example.com/b//c//d;p?q#blarg',
  1101. 'https:/p/a/t/h?s#hash2',
  1102. 'https://p/a/t/h?s#hash2'],
  1103. ['http://example.com/b//c//d;p?q#blarg',
  1104. 'https://u:p@h.com/p/a/t/h?s#hash2',
  1105. 'https://u:p@h.com/p/a/t/h?s#hash2'],
  1106. ['http://example.com/b//c//d;p?q#blarg',
  1107. 'https:/a/b/c/d',
  1108. 'https://a/b/c/d'],
  1109. ['http://example.com/b//c//d;p?q#blarg',
  1110. 'http:#hash2',
  1111. 'http://example.com/b//c//d;p?q#hash2'],
  1112. ['http://example.com/b//c//d;p?q#blarg',
  1113. 'http:/p/a/t/h?s#hash2',
  1114. 'http://example.com/p/a/t/h?s#hash2'],
  1115. ['http://example.com/b//c//d;p?q#blarg',
  1116. 'http://u:p@h.com/p/a/t/h?s#hash2',
  1117. 'http://u:p@h.com/p/a/t/h?s#hash2'],
  1118. ['http://example.com/b//c//d;p?q#blarg',
  1119. 'http:/a/b/c/d',
  1120. 'http://example.com/a/b/c/d'],
  1121. ['/foo/bar/baz', '/../etc/passwd', '/etc/passwd']
  1122. ];
  1123. relativeTests.forEach(function(relativeTest) {
  1124. test('resolve(' + [relativeTest[0], relativeTest[1]] + ')', function() {
  1125. var a = url.resolve(relativeTest[0], relativeTest[1]),
  1126. e = relativeTest[2];
  1127. assert.equal(a, e,
  1128. 'resolve(' + [relativeTest[0], relativeTest[1]] + ') == ' + e +
  1129. '\n actual=' + a);
  1130. });
  1131. });
  1132. // https://github.com/joyent/node/issues/568
  1133. [
  1134. undefined,
  1135. null,
  1136. true,
  1137. false,
  1138. 0.0,
  1139. 0,
  1140. [],
  1141. {}
  1142. ].forEach(function(val) {
  1143. test('parse(' + val + ')', function() {
  1144. assert.throws(function() { url.parse(val); }, TypeError);
  1145. });
  1146. });
  1147. //
  1148. // Tests below taken from Chiron
  1149. // http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js
  1150. //
  1151. // Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
  1152. // used with permission under MIT License
  1153. //
  1154. // Changes marked with @isaacs
  1155. var bases = [
  1156. 'http://a/b/c/d;p?q',
  1157. 'http://a/b/c/d;p?q=1/2',
  1158. 'http://a/b/c/d;p=1/2?q',
  1159. 'fred:///s//a/b/c',
  1160. 'http:///s//a/b/c'
  1161. ];
  1162. //[to, from, result]
  1163. var relativeTests2 = [
  1164. // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html
  1165. ['../c', 'foo:a/b', 'foo:c'],
  1166. ['foo:.', 'foo:a', 'foo:'],
  1167. ['/foo/../../../bar', 'zz:abc', 'zz:/bar'],
  1168. ['/foo/../bar', 'zz:abc', 'zz:/bar'],
  1169. // @isaacs Disagree. Not how web browsers resolve this.
  1170. ['foo/../../../bar', 'zz:abc', 'zz:bar'],
  1171. // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added
  1172. ['foo/../bar', 'zz:abc', 'zz:bar'],
  1173. ['zz:.', 'zz:abc', 'zz:'],
  1174. ['/.', bases[0], 'http://a/'],
  1175. ['/.foo', bases[0], 'http://a/.foo'],
  1176. ['.foo', bases[0], 'http://a/b/c/.foo'],
  1177. // http://gbiv.com/protocols/uri/test/rel_examples1.html
  1178. // examples from RFC 2396
  1179. ['g:h', bases[0], 'g:h'],
  1180. ['g', bases[0], 'http://a/b/c/g'],
  1181. ['./g', bases[0], 'http://a/b/c/g'],
  1182. ['g/', bases[0], 'http://a/b/c/g/'],
  1183. ['/g', bases[0], 'http://a/g'],
  1184. ['//g', bases[0], 'http://g/'],
  1185. // changed with RFC 2396bis
  1186. //('?y', bases[0], 'http://a/b/c/d;p?y'],
  1187. ['?y', bases[0], 'http://a/b/c/d;p?y'],
  1188. ['g?y', bases[0], 'http://a/b/c/g?y'],
  1189. // changed with RFC 2396bis
  1190. //('#s', bases[0], CURRENT_DOC_URI + '#s'],
  1191. ['#s', bases[0], 'http://a/b/c/d;p?q#s'],
  1192. ['g#s', bases[0], 'http://a/b/c/g#s'],
  1193. ['g?y#s', bases[0], 'http://a/b/c/g?y#s'],
  1194. [';x', bases[0], 'http://a/b/c/;x'],
  1195. ['g;x', bases[0], 'http://a/b/c/g;x'],
  1196. ['g;x?y#s' , bases[0], 'http://a/b/c/g;x?y#s'],
  1197. // changed with RFC 2396bis
  1198. //('', bases[0], CURRENT_DOC_URI],
  1199. ['', bases[0], 'http://a/b/c/d;p?q'],
  1200. ['.', bases[0], 'http://a/b/c/'],
  1201. ['./', bases[0], 'http://a/b/c/'],
  1202. ['..', bases[0], 'http://a/b/'],
  1203. ['../', bases[0], 'http://a/b/'],
  1204. ['../g', bases[0], 'http://a/b/g'],
  1205. ['../..', bases[0], 'http://a/'],
  1206. ['../../', bases[0], 'http://a/'],
  1207. ['../../g' , bases[0], 'http://a/g'],
  1208. ['../../../g', bases[0], ('http://a/../g', 'http://a/g')],
  1209. ['../../../../g', bases[0], ('http://a/../../g', 'http://a/g')],
  1210. // changed with RFC 2396bis
  1211. //('/./g', bases[0], 'http://a/./g'],
  1212. ['/./g', bases[0], 'http://a/g'],
  1213. // changed with RFC 2396bis
  1214. //('/../g', bases[0], 'http://a/../g'],
  1215. ['/../g', bases[0], 'http://a/g'],
  1216. ['g.', bases[0], 'http://a/b/c/g.'],
  1217. ['.g', bases[0], 'http://a/b/c/.g'],
  1218. ['g..', bases[0], 'http://a/b/c/g..'],
  1219. ['..g', bases[0], 'http://a/b/c/..g'],
  1220. ['./../g', bases[0], 'http://a/b/g'],
  1221. ['./g/.', bases[0], 'http://a/b/c/g/'],
  1222. ['g/./h', bases[0], 'http://a/b/c/g/h'],
  1223. ['g/../h', bases[0], 'http://a/b/c/h'],
  1224. ['g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'],
  1225. ['g;x=1/../y', bases[0], 'http://a/b/c/y'],
  1226. ['g?y/./x', bases[0], 'http://a/b/c/g?y/./x'],
  1227. ['g?y/../x', bases[0], 'http://a/b/c/g?y/../x'],
  1228. ['g#s/./x', bases[0], 'http://a/b/c/g#s/./x'],
  1229. ['g#s/../x', bases[0], 'http://a/b/c/g#s/../x'],
  1230. ['http:g', bases[0], ('http:g', 'http://a/b/c/g')],
  1231. ['http:', bases[0], ('http:', bases[0])],
  1232. // not sure where this one originated
  1233. ['/a/b/c/./../../g', bases[0], 'http://a/a/g'],
  1234. // http://gbiv.com/protocols/uri/test/rel_examples2.html
  1235. // slashes in base URI's query args
  1236. ['g', bases[1], 'http://a/b/c/g'],
  1237. ['./g', bases[1], 'http://a/b/c/g'],
  1238. ['g/', bases[1], 'http://a/b/c/g/'],
  1239. ['/g', bases[1], 'http://a/g'],
  1240. ['//g', bases[1], 'http://g/'],
  1241. // changed in RFC 2396bis
  1242. //('?y', bases[1], 'http://a/b/c/?y'],
  1243. ['?y', bases[1], 'http://a/b/c/d;p?y'],
  1244. ['g?y', bases[1], 'http://a/b/c/g?y'],
  1245. ['g?y/./x' , bases[1], 'http://a/b/c/g?y/./x'],
  1246. ['g?y/../x', bases[1], 'http://a/b/c/g?y/../x'],
  1247. ['g#s', bases[1], 'http://a/b/c/g#s'],
  1248. ['g#s/./x' , bases[1], 'http://a/b/c/g#s/./x'],
  1249. ['g#s/../x', bases[1], 'http://a/b/c/g#s/../x'],
  1250. ['./', bases[1], 'http://a/b/c/'],
  1251. ['../', bases[1], 'http://a/b/'],
  1252. ['../g', bases[1], 'http://a/b/g'],
  1253. ['../../', bases[1], 'http://a/'],
  1254. ['../../g' , bases[1], 'http://a/g'],
  1255. // http://gbiv.com/protocols/uri/test/rel_examples3.html
  1256. // slashes in path params
  1257. // all of these changed in RFC 2396bis
  1258. ['g', bases[2], 'http://a/b/c/d;p=1/g'],
  1259. ['./g', bases[2], 'http://a/b/c/d;p=1/g'],
  1260. ['g/', bases[2], 'http://a/b/c/d;p=1/g/'],
  1261. ['g?y', bases[2], 'http://a/b/c/d;p=1/g?y'],
  1262. [';x', bases[2], 'http://a/b/c/d;p=1/;x'],
  1263. ['g;x', bases[2], 'http://a/b/c/d;p=1/g;x'],
  1264. ['g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'],
  1265. ['g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'],
  1266. ['./', bases[2], 'http://a/b/c/d;p=1/'],
  1267. ['../', bases[2], 'http://a/b/c/'],
  1268. ['../g', bases[2], 'http://a/b/c/g'],
  1269. ['../../', bases[2], 'http://a/b/'],
  1270. ['../../g' , bases[2], 'http://a/b/g'],
  1271. // http://gbiv.com/protocols/uri/test/rel_examples4.html
  1272. // double and triple slash, unknown scheme
  1273. ['g:h', bases[3], 'g:h'],
  1274. ['g', bases[3], 'fred:///s//a/b/g'],
  1275. ['./g', bases[3], 'fred:///s//a/b/g'],
  1276. ['g/', bases[3], 'fred:///s//a/b/g/'],
  1277. ['/g', bases[3], 'fred:///g'], // may change to fred:///s//a/g
  1278. ['//g', bases[3], 'fred://g'], // may change to fred:///s//g
  1279. ['//g/x', bases[3], 'fred://g/x'], // may change to fred:///s//g/x
  1280. ['///g', bases[3], 'fred:///g'],
  1281. ['./', bases[3], 'fred:///s//a/b/'],
  1282. ['../', bases[3], 'fred:///s//a/'],
  1283. ['../g', bases[3], 'fred:///s//a/g'],
  1284. ['../../', bases[3], 'fred:///s//'],
  1285. ['../../g' , bases[3], 'fred:///s//g'],
  1286. ['../../../g', bases[3], 'fred:///s/g'],
  1287. // may change to fred:///s//a/../../../g
  1288. ['../../../../g', bases[3], 'fred:///g'],
  1289. // http://gbiv.com/protocols/uri/test/rel_examples5.html
  1290. // double and triple slash, well-known scheme
  1291. ['g:h', bases[4], 'g:h'],
  1292. ['g', bases[4], 'http:///s//a/b/g'],
  1293. ['./g', bases[4], 'http:///s//a/b/g'],
  1294. ['g/', bases[4], 'http:///s//a/b/g/'],
  1295. ['/g', bases[4], 'http:///g'], // may change to http:///s//a/g
  1296. ['//g', bases[4], 'http://g/'], // may change to http:///s//g
  1297. ['//g/x', bases[4], 'http://g/x'], // may change to http:///s//g/x
  1298. ['///g', bases[4], 'http:///g'],
  1299. ['./', bases[4], 'http:///s//a/b/'],
  1300. ['../', bases[4], 'http:///s//a/'],
  1301. ['../g', bases[4], 'http:///s//a/g'],
  1302. ['../../', bases[4], 'http:///s//'],
  1303. ['../../g' , bases[4], 'http:///s//g'],
  1304. // may change to http:///s//a/../../g
  1305. ['../../../g', bases[4], 'http:///s/g'],
  1306. // may change to http:///s//a/../../../g
  1307. ['../../../../g', bases[4], 'http:///g'],
  1308. // from Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py
  1309. ['bar:abc', 'foo:xyz', 'bar:abc'],
  1310. ['../abc', 'http://example/x/y/z', 'http://example/x/abc'],
  1311. ['http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'],
  1312. ['../r', 'http://ex/x/y/z', 'http://ex/x/r'],
  1313. ['q/r', 'http://ex/x/y', 'http://ex/x/q/r'],
  1314. ['q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'],
  1315. ['q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'],
  1316. ['ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'],
  1317. ['', 'http://ex/x/y', 'http://ex/x/y'],
  1318. ['', 'http://ex/x/y/', 'http://ex/x/y/'],
  1319. ['', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'],
  1320. ['z/', 'http://ex/x/y/', 'http://ex/x/y/z/'],
  1321. ['#Animal',
  1322. 'file:/swap/test/animal.rdf',
  1323. 'file:/swap/test/animal.rdf#Animal'],
  1324. ['../abc', 'file:/e/x/y/z', 'file:/e/x/abc'],
  1325. ['/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'],
  1326. ['../r', 'file:/ex/x/y/z', 'file:/ex/x/r'],
  1327. ['/r', 'file:/ex/x/y/z', 'file:/r'],
  1328. ['q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'],
  1329. ['q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'],
  1330. ['q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'],
  1331. ['q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'],
  1332. ['ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'],
  1333. ['', 'file:/ex/x/y', 'file:/ex/x/y'],
  1334. ['', 'file:/ex/x/y/', 'file:/ex/x/y/'],
  1335. ['', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'],
  1336. ['z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'],
  1337. ['file://meetings.example.com/cal#m1',
  1338. 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3',
  1339. 'file://meetings.example.com/cal#m1'],
  1340. ['file://meetings.example.com/cal#m1',
  1341. 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3',
  1342. 'file://meetings.example.com/cal#m1'],
  1343. ['./#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'],
  1344. ['./#', 'file:/some/dir/foo', 'file:/some/dir/#'],
  1345. // Ryan Lee
  1346. ['./', 'http://example/x/abc.efg', 'http://example/x/'],
  1347. // Graham Klyne's tests
  1348. // http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls
  1349. // 01-31 are from Connelly's cases
  1350. // 32-49
  1351. ['./q:r', 'http://ex/x/y', 'http://ex/x/q:r'],
  1352. ['./p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'],
  1353. ['?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'],
  1354. ['y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'],
  1355. ['local/qual@domain.org#frag',
  1356. 'mailto:local',
  1357. 'mailto:local/qual@domain.org#frag'],
  1358. ['more/qual2@domain2.org#frag',
  1359. 'mailto:local/qual1@domain1.org',
  1360. 'mailto:local/more/qual2@domain2.org#frag'],
  1361. ['y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'],
  1362. ['/x/y?q', 'http://ex?p', 'http://ex/x/y?q'],
  1363. ['c/d', 'foo:a/b', 'foo:a/c/d'],
  1364. ['/c/d', 'foo:a/b', 'foo:/c/d'],
  1365. ['', 'foo:a/b?c#d', 'foo:a/b?c'],
  1366. ['b/c', 'foo:a', 'foo:b/c'],
  1367. ['../b/c', 'foo:/a/y/z', 'foo:/a/b/c'],
  1368. ['./b/c', 'foo:a', 'foo:b/c'],
  1369. ['/./b/c', 'foo:a', 'foo:/b/c'],
  1370. ['../../d', 'foo://a//b/c', 'foo://a/d'],
  1371. ['.', 'foo:a', 'foo:'],
  1372. ['..', 'foo:a', 'foo:'],
  1373. // 50-57[cf. TimBL comments --
  1374. // http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html,
  1375. // http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html)
  1376. ['abc', 'http://example/x/y%2Fz', 'http://example/x/abc'],
  1377. ['../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'],
  1378. ['../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'],
  1379. ['abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'],
  1380. ['q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'],
  1381. ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
  1382. ['/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'],
  1383. ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
  1384. // 70-77
  1385. ['local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'],
  1386. ['local2@domain2?query2',
  1387. 'mailto:local1@domain1',
  1388. 'mailto:local2@domain2?query2'],
  1389. ['local2@domain2?query2',
  1390. 'mailto:local1@domain1?query1',
  1391. 'mailto:local2@domain2?query2'],
  1392. ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
  1393. ['local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'],
  1394. ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
  1395. ['http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'],
  1396. ['http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'],
  1397. // 82-88
  1398. // @isaacs Disagree. Not how browsers do it.
  1399. // ['http:this', 'http://example.org/base/uri', 'http:this'],
  1400. // @isaacs Added
  1401. ['http:this', 'http://example.org/base/uri', 'http://example.org/base/this'],
  1402. ['http:this', 'http:base', 'http:this'],
  1403. ['.//g', 'f:/a', 'f://g'],
  1404. ['b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'],
  1405. ['m2@example.ord/c2@example.org',
  1406. 'mid:m@example.ord/c@example.org',
  1407. 'mid:m@example.ord/m2@example.ord/c2@example.org'],
  1408. ['mini1.xml',
  1409. 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/',
  1410. 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'],
  1411. ['../b/c', 'foo:a/y/z', 'foo:a/b/c'],
  1412. //changeing auth
  1413. ['http://diff:auth@www.example.com',
  1414. 'http://asdf:qwer@www.example.com',
  1415. 'http://diff:auth@www.example.com/']
  1416. ];
  1417. relativeTests2.forEach(function(relativeTest) {
  1418. test('resolve(' + [relativeTest[1], relativeTest[0]] + ')', function() {
  1419. var a = url.resolve(relativeTest[1], relativeTest[0]),
  1420. e = relativeTest[2];
  1421. assert.equal(a, e,
  1422. 'resolve(' + [relativeTest[1], relativeTest[0]] + ') == ' + e +
  1423. '\n actual=' + a);
  1424. });
  1425. });
  1426. //if format and parse are inverse operations then
  1427. //resolveObject(parse(x), y) == parse(resolve(x, y))
  1428. //host and hostname are special, in this case a '' value is important
  1429. var emptyIsImportant = {'host': true, 'hostname': ''};
  1430. //format: [from, path, expected]
  1431. relativeTests.forEach(function(relativeTest) {
  1432. test('resolveObject(' + [relativeTest[0], relativeTest[1]] + ')', function() {
  1433. var actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]),
  1434. expected = url.parse(relativeTest[2]);
  1435. assert.deepEqual(actual, expected);
  1436. expected = relativeTest[2];
  1437. actual = url.format(actual);
  1438. assert.equal(actual, expected,
  1439. 'format(' + actual + ') == ' + expected + '\nactual:' + actual);
  1440. });
  1441. });
  1442. //format: [to, from, result]
  1443. // the test: ['.//g', 'f:/a', 'f://g'] is a fundamental problem
  1444. // url.parse('f:/a') does not have a host
  1445. // url.resolve('f:/a', './/g') does not have a host because you have moved
  1446. // down to the g directory. i.e. f: //g, however when this url is parsed
  1447. // f:// will indicate that the host is g which is not the case.
  1448. // it is unclear to me how to keep this information from being lost
  1449. // it may be that a pathname of ////g should collapse to /g but this seems
  1450. // to be a lot of work for an edge case. Right now I remove the test
  1451. if (relativeTests2[181][0] === './/g' &&
  1452. relativeTests2[181][1] === 'f:/a' &&
  1453. relativeTests2[181][2] === 'f://g') {
  1454. relativeTests2.splice(181, 1);
  1455. }
  1456. relativeTests2.forEach(function(relativeTest) {
  1457. test('resolveObject(' + [relativeTest[1], relativeTest[0]] + ')', function() {
  1458. var actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]),
  1459. expected = url.parse(relativeTest[2]);
  1460. assert.deepEqual(actual, expected);
  1461. var expected = relativeTest[2],
  1462. actual = url.format(actual);
  1463. assert.equal(actual, expected,
  1464. 'format(' + relativeTest[1] + ') == ' + expected +
  1465. '\nactual:' + actual);
  1466. });
  1467. });