url-toolkit.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. const URLToolkit = require('../src/url-toolkit');
  2. describe('url toolkit', () => {
  3. describe('works with a selection of valid urls', () => {
  4. // From spec: https://tools.ietf.org/html/rfc1808#section-5.1
  5. test('http://a/b/c/d;p?q#f', 'g:h', 'g:h');
  6. test('http://a/b/c/d;p?q#f', 'g', 'http://a/b/c/g');
  7. test('http://a/b/c/d;p?q#f', './g', 'http://a/b/c/g');
  8. test('http://a/b/c/d;p?q#f', 'g/', 'http://a/b/c/g/');
  9. test('http://a/b/c/d;p?q#f', '/g', 'http://a/g');
  10. test('http://a/b/c/d;p?q#f', '//g', 'http://g');
  11. test('http://a/b/c/d;p?q#f', '?y', 'http://a/b/c/d;p?y');
  12. test('http://a/b/c/d;p?q#f', 'g?y', 'http://a/b/c/g?y');
  13. test('http://a/b/c/d;p?q#f', 'g?y/./x', 'http://a/b/c/g?y/./x');
  14. test('http://a/b/c/d;p?q#f', '#s', 'http://a/b/c/d;p?q#s');
  15. test('http://a/b/c/d;p?q#f', 'g#s', 'http://a/b/c/g#s');
  16. test('http://a/b/c/d;p?q#f', 'g#s/./x', 'http://a/b/c/g#s/./x');
  17. test('http://a/b/c/d;p?q#f', 'g?y#s', 'http://a/b/c/g?y#s');
  18. test('http://a/b/c/d;p?q#f', ';x', 'http://a/b/c/d;x');
  19. test('http://a/b/c/d;p?q#f', 'g;x', 'http://a/b/c/g;x');
  20. test('http://a/b/c/d;p?q#f', 'g;x?y#s', 'http://a/b/c/g;x?y#s');
  21. test('http://a/b/c/d;p?q#f', '.', 'http://a/b/c/');
  22. test('http://a/b/c/d;p?q#f', './', 'http://a/b/c/');
  23. test('http://a/b/c/d;p?q#f', '..', 'http://a/b/');
  24. test('http://a/b/c/d;p?q#f', '../', 'http://a/b/');
  25. test('http://a/b/c/d;p?q#f', '../g', 'http://a/b/g');
  26. test('http://a/b/c/d;p?q#f', '../..', 'http://a/');
  27. test('http://a/b/c/d;p?q#f', '../../', 'http://a/');
  28. test('http://a/b/c/d;p?q#f', '../../g', 'http://a/g');
  29. test('http://a/b/c/d;p?q#f', '', 'http://a/b/c/d;p?q#f');
  30. test('http://a/b/c/d;p?q#f', '../../../g', 'http://a/../g');
  31. test('http://a/b/c/d;p?q#f', '../../../../g', 'http://a/../../g');
  32. test('http://a/b/c/d;p?q#f', '/./g', 'http://a/./g');
  33. test('http://a/b/c/d;p?q#f', '/../g', 'http://a/../g');
  34. test('http://a/b/c/d;p?q#f', 'g.', 'http://a/b/c/g.');
  35. test('http://a/b/c/d;p?q#f', '.g', 'http://a/b/c/.g');
  36. test('http://a/b/c/d;p?q#f', 'g..', 'http://a/b/c/g..');
  37. test('http://a/b/c/d;p?q#f', '..g', 'http://a/b/c/..g');
  38. test('http://a/b/c/d;p?q#f', './../g', 'http://a/b/g');
  39. test('http://a/b/c/d;p?q#f', './g/.', 'http://a/b/c/g/');
  40. test('http://a/b/c/d;p?q#f', 'g/./h', 'http://a/b/c/g/h');
  41. test('http://a/b/c/d;p?q#f', 'g/../h', 'http://a/b/c/h');
  42. test('http://a/b/c/d;p?q#f', 'http:g', 'http:g');
  43. test('http://a/b/c/d;p?q#f', 'http:', 'http:');
  44. // Custom
  45. test(
  46. 'http://a.com/b/cd/./e.m3u8?test=1#something',
  47. '',
  48. 'http://a.com/b/cd/./e.m3u8?test=1#something'
  49. );
  50. test(
  51. 'http://a.com/b/cd/./e.m3u8?test=1#something',
  52. '',
  53. 'http://a.com/b/cd/e.m3u8?test=1#something',
  54. { alwaysNormalize: true }
  55. );
  56. test(
  57. 'http://a.com/b/cd/e.m3u8',
  58. 'https://example.com/z.ts',
  59. 'https://example.com/z.ts'
  60. );
  61. test('http://a.com/b/cd/e.m3u8', 'g:h', 'g:h');
  62. test(
  63. 'http://a.com/b/cd/e.m3u8',
  64. 'https://example.com:8080/z.ts',
  65. 'https://example.com:8080/z.ts'
  66. );
  67. test('http://a.com/b/cd/e.m3u8', 'z.ts', 'http://a.com/b/cd/z.ts');
  68. test(
  69. 'http://a.com:8080/b/cd/e.m3u8',
  70. 'z.ts',
  71. 'http://a.com:8080/b/cd/z.ts'
  72. );
  73. test('http://a.com/b/cd/', 'z.ts', 'http://a.com/b/cd/z.ts');
  74. test('http://a.com/b/cd', 'z.ts', 'http://a.com/b/z.ts');
  75. test('http://a.com/', 'z.ts', 'http://a.com/z.ts');
  76. test('http://a.com/?test=1', 'z.ts', 'http://a.com/z.ts');
  77. test('http://a.com', 'z.ts', 'http://a.com/z.ts');
  78. test('http://a.com?test=1', 'z.ts', 'http://a.com/z.ts');
  79. test('http://a.com/b/cd?test=1', 'z.ts', 'http://a.com/b/z.ts');
  80. test('http://a.com/b/cd#something', 'z.ts', 'http://a.com/b/z.ts');
  81. test('http://a.com/b/cd?test=1#something', 'z.ts', 'http://a.com/b/z.ts');
  82. test(
  83. 'http://a.com/b/cd?test=1#something',
  84. 'z.ts?abc=1',
  85. 'http://a.com/b/z.ts?abc=1'
  86. );
  87. test(
  88. 'http://a.com/b/cd?test=1#something',
  89. 'z.ts#test',
  90. 'http://a.com/b/z.ts#test'
  91. );
  92. test(
  93. 'http://a.com/b/cd?test=1#something',
  94. 'z.ts?abc=1#test',
  95. 'http://a.com/b/z.ts?abc=1#test'
  96. );
  97. test('http://a.com/b/cd?test=1#something', ';x', 'http://a.com/b/cd;x');
  98. test('http://a.com/b/cd?test=1#something', './;x', 'http://a.com/b/;x');
  99. test('http://a.com/b/cd?test=1#something', 'g;x', 'http://a.com/b/g;x');
  100. test('http://a_b.com/b/cd?test=1#something', 'g;x', 'http://a_b.com/b/g;x');
  101. test('http://a-b.com/b/cd?test=1#something', 'g;x', 'http://a-b.com/b/g;x');
  102. test('http://a.b.com/b/cd?test=1#something', 'g;x', 'http://a.b.com/b/g;x');
  103. test('http://a~b.com/b/cd?test=1#something', 'g;x', 'http://a~b.com/b/g;x');
  104. test('a.com', 'z.ts', 'a.com/z.ts');
  105. test('a.com/', 'z.ts', 'a.com/z.ts');
  106. test('a.com/b/cd', 'z.ts', 'a.com/b/z.ts');
  107. test('a.com/b/cd', '../z.ts', 'a.com/z.ts');
  108. test('a.com/b/cd', '/z.ts', 'a.com/z.ts');
  109. test('a.com/b/cd', '/b/z.ts', 'a.com/b/z.ts');
  110. test(
  111. 'http://a.com/b/cd/e.m3u8?test=1#something',
  112. 'subdir/z.ts?abc=1#test',
  113. 'http://a.com/b/cd/subdir/z.ts?abc=1#test'
  114. );
  115. test(
  116. 'http://a.com/b/cd/e.m3u8?test=1#something',
  117. '/subdir/z.ts?abc=1#test',
  118. 'http://a.com/subdir/z.ts?abc=1#test'
  119. );
  120. test(
  121. 'http://a.com/b/cd/e.m3u8?test=1#something',
  122. '//example.com/z.ts?abc=1#test',
  123. 'http://example.com/z.ts?abc=1#test'
  124. );
  125. test(
  126. 'https://a.com/b/cd/e.m3u8?test=1#something',
  127. '//example.com/z.ts?abc=1#test',
  128. 'https://example.com/z.ts?abc=1#test'
  129. );
  130. test(
  131. 'https://a.com/b/cd/e.m3u8?test=1#something',
  132. './z.ts?abc=1#test',
  133. 'https://a.com/b/cd/z.ts?abc=1#test'
  134. );
  135. test(
  136. 'https://a.com/b/cd/e.m3u8?test=1#something',
  137. '../z.ts?abc=1#test',
  138. 'https://a.com/b/z.ts?abc=1#test'
  139. );
  140. test(
  141. 'https://a.com/b/cd/e.m3u8?test=1#something',
  142. './../z.ts?abc=1#test',
  143. 'https://a.com/b/z.ts?abc=1#test'
  144. );
  145. test(
  146. 'https://a.com/b/cd/e.m3u8?test=1#something',
  147. '././z.ts?abc=1#test',
  148. 'https://a.com/b/cd/z.ts?abc=1#test'
  149. );
  150. test(
  151. 'https://a.com/b/cd/e/f.m3u8?test=1#something',
  152. '../../z.ts?abc=1#test',
  153. 'https://a.com/b/z.ts?abc=1#test'
  154. );
  155. test(
  156. 'https://a.com/b/cd/e.m3u8?test=1#something',
  157. '../../z.ts?abc=1#test',
  158. 'https://a.com/z.ts?abc=1#test'
  159. );
  160. test(
  161. 'https://a.com/b/cd/e.m3u8?test=1#something',
  162. '../../z.ts?abc=1&something=blah/./../test#test',
  163. 'https://a.com/z.ts?abc=1&something=blah/./../test#test'
  164. );
  165. test(
  166. 'https://a.com/b/cd/e/f.m3u8?test=1#something',
  167. './../../z.ts?abc=1#test',
  168. 'https://a.com/b/z.ts?abc=1#test'
  169. );
  170. test(
  171. 'https://a.com/b/cd/e.m3u8?test=1#something',
  172. 'subdir/pointless/../z.ts?abc=1#test',
  173. 'https://a.com/b/cd/subdir/z.ts?abc=1#test'
  174. );
  175. test(
  176. 'https://a.com/b/cd/e.m3u8?test=1#something',
  177. '/subdir/pointless/../z.ts?abc=1#test',
  178. 'https://a.com/subdir/z.ts?abc=1#test',
  179. { alwaysNormalize: true }
  180. );
  181. test(
  182. 'https://a.com/b/cd/e.m3u8?test=1#something',
  183. '/subdir/pointless/../z.ts?abc=1#test',
  184. 'https://a.com/subdir/pointless/../z.ts?abc=1#test'
  185. );
  186. test(
  187. 'https://a.com/b/cd/e.m3u8?test=1#something',
  188. '//example.com/subdir/pointless/../z.ts?abc=1#test',
  189. 'https://example.com/subdir/z.ts?abc=1#test',
  190. { alwaysNormalize: true }
  191. );
  192. test(
  193. 'https://a.com/b/cd/e.m3u8?test=1#something',
  194. '//example.com/subdir/pointless/../z.ts?abc=1#test',
  195. 'https://example.com/subdir/pointless/../z.ts?abc=1#test'
  196. );
  197. test(
  198. 'https://a-b.something.com/b/cd/e.m3u8?test=1#something',
  199. '//example.com/subdir/pointless/../z.ts?abc=1#test',
  200. 'https://example.com/subdir/z.ts?abc=1#test',
  201. { alwaysNormalize: true }
  202. );
  203. test(
  204. 'https://a-b.something.com/b/cd/e.m3u8?test=1#something',
  205. '//example.com/subdir/pointless/../z.ts?abc=1#test',
  206. 'https://example.com/subdir/pointless/../z.ts?abc=1#test'
  207. );
  208. test(
  209. '//a.com/b/cd/e.m3u8',
  210. 'https://example.com/z.ts',
  211. 'https://example.com/z.ts'
  212. );
  213. test('//a.com/b/cd/e.m3u8', '//example.com/z.ts', '//example.com/z.ts');
  214. test(
  215. '//a.com/b/cd/e.m3u8',
  216. '/example.com/z.ts',
  217. '//a.com/example.com/z.ts'
  218. );
  219. test('//a.com/b/cd/e.m3u8', 'g:h', 'g:h');
  220. test(
  221. '//a.com/b/cd/e.m3u8',
  222. 'https://example.com:8080/z.ts',
  223. 'https://example.com:8080/z.ts'
  224. );
  225. test('//a.com/b/cd/e.m3u8', 'z.ts', '//a.com/b/cd/z.ts');
  226. test('//a.com/b/cd/e.m3u8', '../../z.ts', '//a.com/z.ts');
  227. test('//a.com/b/cd/e.m3u8', '../../../z.ts', '//a.com/../z.ts');
  228. test(
  229. '/a/b/cd/e.m3u8',
  230. 'https://example.com/z.ts',
  231. 'https://example.com/z.ts'
  232. );
  233. test('/a/b/cd/e.m3u8', '/example.com/z.ts', '/example.com/z.ts');
  234. test('/a/b/cd/e.m3u8', '//example.com/z.ts', '//example.com/z.ts');
  235. test('/a/b/cd/e.m3u8', 'g:h', 'g:h');
  236. test(
  237. '/a/b/cd/e.m3u8',
  238. 'https://example.com:8080/z.ts',
  239. 'https://example.com:8080/z.ts'
  240. );
  241. test('/a/b/cd/e.m3u8', 'z.ts', '/a/b/cd/z.ts');
  242. test('/a/b/cd/e.m3u8', '../../../z.ts', '/z.ts');
  243. test('http://ö.de/a/b', 'z.ts', 'http://ö.de/a/z.ts');
  244. test('http://ö.de/a', 'z.ts', 'http://ö.de/z.ts');
  245. test('http://ö.de/', 'z.ts', 'http://ö.de/z.ts');
  246. test('http://ö.de', 'z.ts', 'http://ö.de/z.ts');
  247. test('ö.de', 'z.ts', 'ö.de/z.ts');
  248. test('http://a/b/c/d;p?q', './', 'http://a/b/c/');
  249. test('http://a/b/c/d;p?q', '.', 'http://a/b/c/');
  250. test('http://a/b/c/d;p?q', '../', 'http://a/b/');
  251. test('http://a/b/c/d;p?q', '..', 'http://a/b/');
  252. test(
  253. 'http://a.com/b/cd/e.m3u8?test=1#something',
  254. '',
  255. 'http://a.com/b/cd/e.m3u8?test=1#something'
  256. );
  257. test(
  258. 'http://a.com/b/cd/e.m3u8?test=1#something',
  259. 'a_:b',
  260. 'http://a.com/b/cd/a_:b'
  261. );
  262. test('http://a.com/b/cd/e.m3u8?test=1#something', 'a:b', 'a:b');
  263. test(
  264. 'http://a.com/b/cd/e.m3u8?test=1#something',
  265. './a:b',
  266. 'http://a.com/b/cd/a:b'
  267. );
  268. test(
  269. 'http://a.com/expiretime=111;dirmatch=true/master.m3u8',
  270. './a:b',
  271. 'http://a.com/expiretime=111;dirmatch=true/a:b'
  272. );
  273. test('http://0.0.0.0/a/b.c', 'd', 'http://0.0.0.0/a/d');
  274. test('http://[0:0:0:0::0]/a/b.c', 'd', 'http://[0:0:0:0::0]/a/d');
  275. test('http://example.com/', 'a#\nb', 'http://example.com/a#\nb');
  276. // in the URL living standard (https://url.spec.whatwg.org/)
  277. // `http` is a 'special scheme', and that results in
  278. // the `///` becoming `//`, meaning `netLoc` would essentially be
  279. // `//example.com` instead of `//`
  280. // This library is specifically RFC 1808, which does not have these
  281. // special cases.
  282. test('http:///example.com/a/', '../../b', 'http:///b');
  283. });
  284. });
  285. function test(base, relative, expected, opts) {
  286. opts = opts || {};
  287. it(`"${base}" + "${relative}" ${JSON.stringify(opts)}`, () => {
  288. expect(URLToolkit.parseURL(base)).toMatchSnapshot();
  289. expect(URLToolkit.parseURL(relative)).toMatchSnapshot();
  290. expect(URLToolkit.buildURLFromParts(URLToolkit.parseURL(relative))).toBe(
  291. relative
  292. );
  293. expect(URLToolkit.buildURLFromParts(URLToolkit.parseURL(base))).toBe(base);
  294. expect(URLToolkit.buildAbsoluteURL(base, relative, opts)).toBe(expected);
  295. });
  296. }