test.js 43 KB

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