turi.nim 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. discard """
  2. matrix: "--mm:refc; --mm:orc"
  3. targets: "c js"
  4. """
  5. import std/uri
  6. from std/uri {.all.} as uri2 import removeDotSegments
  7. from std/sequtils import toSeq
  8. import std/assertions
  9. template main() =
  10. block: # encodeUrl, decodeUrl
  11. const test1 = "abc\L+def xyz"
  12. doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
  13. doAssert decodeUrl(encodeUrl(test1)) == test1
  14. doAssert encodeUrl(test1, false) == "abc%0A%2Bdef%20xyz"
  15. doAssert decodeUrl(encodeUrl(test1, false), false) == test1
  16. doAssert decodeUrl(encodeUrl(test1)) == test1
  17. block: # removeDotSegments
  18. doAssert removeDotSegments("/foo/bar/baz") == "/foo/bar/baz"
  19. doAssert removeDotSegments("") == "" # empty test
  20. doAssert removeDotSegments(".") == "." # trailing period
  21. doAssert removeDotSegments("a1/a2/../a3/a4/a5/./a6/a7/././") == "a1/a3/a4/a5/a6/a7/"
  22. doAssert removeDotSegments("https://a1/a2/../a3/a4/a5/./a6/a7/././") == "https://a1/a3/a4/a5/a6/a7/"
  23. doAssert removeDotSegments("http://a1/a2") == "http://a1/a2"
  24. doAssert removeDotSegments("http://www.ai.") == "http://www.ai."
  25. when false: # xxx these cases are buggy
  26. # this should work, refs https://webmasters.stackexchange.com/questions/73934/how-can-urls-have-a-dot-at-the-end-e-g-www-bla-de
  27. doAssert removeDotSegments("http://www.ai./") == "http://www.ai./" # fails
  28. echo removeDotSegments("http://www.ai./") # http://www.ai/
  29. echo removeDotSegments("a/b.../c") # b.c
  30. echo removeDotSegments("a/b../c") # bc
  31. echo removeDotSegments("a/.../c") # .c
  32. echo removeDotSegments("a//../b") # a/b
  33. echo removeDotSegments("a/b/c//") # a/b/c//
  34. block: # parseUri
  35. block:
  36. let org = "udp://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
  37. let url = parseUri(org)
  38. doAssert url.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
  39. let newUrl = parseUri($url)
  40. doAssert newUrl.hostname == "2001:0db8:85a3:0000:0000:8a2e:0370:7334" # true
  41. block:
  42. let str = "http://localhost"
  43. let test = parseUri(str)
  44. doAssert test.path == ""
  45. block:
  46. let str = "http://localhost/"
  47. let test = parseUri(str)
  48. doAssert test.path == "/"
  49. block:
  50. let str = "http://localhost:8080/test"
  51. let test = parseUri(str)
  52. doAssert test.scheme == "http"
  53. doAssert test.port == "8080"
  54. doAssert test.path == "/test"
  55. doAssert test.hostname == "localhost"
  56. doAssert($test == str)
  57. block:
  58. let str = "foo://username:password@example.com:8042/over/there" &
  59. "/index.dtb?type=animal&name=narwhal#nose"
  60. let test = parseUri(str)
  61. doAssert test.scheme == "foo"
  62. doAssert test.username == "username"
  63. doAssert test.password == "password"
  64. doAssert test.hostname == "example.com"
  65. doAssert test.port == "8042"
  66. doAssert test.path == "/over/there/index.dtb"
  67. doAssert test.query == "type=animal&name=narwhal"
  68. doAssert test.anchor == "nose"
  69. doAssert($test == str)
  70. block:
  71. # IPv6 address
  72. let str = "foo://[::1]:1234/bar?baz=true&qux#quux"
  73. let uri = parseUri(str)
  74. doAssert uri.scheme == "foo"
  75. doAssert uri.hostname == "::1"
  76. doAssert uri.port == "1234"
  77. doAssert uri.path == "/bar"
  78. doAssert uri.query == "baz=true&qux"
  79. doAssert uri.anchor == "quux"
  80. block:
  81. let str = "urn:example:animal:ferret:nose"
  82. let test = parseUri(str)
  83. doAssert test.scheme == "urn"
  84. doAssert test.path == "example:animal:ferret:nose"
  85. doAssert($test == str)
  86. block:
  87. let str = "mailto:username@example.com?subject=Topic"
  88. let test = parseUri(str)
  89. doAssert test.scheme == "mailto"
  90. doAssert test.username == "username"
  91. doAssert test.hostname == "example.com"
  92. doAssert test.query == "subject=Topic"
  93. doAssert($test == str)
  94. block:
  95. let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
  96. let test = parseUri(str)
  97. doAssert test.scheme == "magnet"
  98. doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
  99. doAssert($test == str)
  100. block:
  101. let str = "/test/foo/bar?q=2#asdf"
  102. let test = parseUri(str)
  103. doAssert test.scheme == ""
  104. doAssert test.path == "/test/foo/bar"
  105. doAssert test.query == "q=2"
  106. doAssert test.anchor == "asdf"
  107. doAssert($test == str)
  108. block:
  109. let str = "test/no/slash"
  110. let test = parseUri(str)
  111. doAssert test.path == "test/no/slash"
  112. doAssert($test == str)
  113. block:
  114. let str = "//git@github.com:dom96/packages"
  115. let test = parseUri(str)
  116. doAssert test.scheme == ""
  117. doAssert test.username == "git"
  118. doAssert test.hostname == "github.com"
  119. doAssert test.port == "dom96"
  120. doAssert test.path == "/packages"
  121. block:
  122. let str = "file:///foo/bar/baz.txt"
  123. let test = parseUri(str)
  124. doAssert test.scheme == "file"
  125. doAssert test.username == ""
  126. doAssert test.hostname == ""
  127. doAssert test.port == ""
  128. doAssert test.path == "/foo/bar/baz.txt"
  129. block: # combine
  130. block:
  131. let concat = combine(parseUri("http://google.com/foo/bar/"), parseUri("baz"))
  132. doAssert concat.path == "/foo/bar/baz"
  133. doAssert concat.hostname == "google.com"
  134. doAssert concat.scheme == "http"
  135. block:
  136. let concat = combine(parseUri("http://google.com/foo"), parseUri("/baz"))
  137. doAssert concat.path == "/baz"
  138. doAssert concat.hostname == "google.com"
  139. doAssert concat.scheme == "http"
  140. block:
  141. let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
  142. doAssert concat.path == "/foo/bar"
  143. block:
  144. let concat = combine(parseUri("http://google.com/foo/test"), parseUri("/bar"))
  145. doAssert concat.path == "/bar"
  146. block:
  147. let concat = combine(parseUri("http://google.com/foo/test"), parseUri("bar"))
  148. doAssert concat.path == "/foo/bar"
  149. block:
  150. let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar"))
  151. doAssert concat.path == "/foo/test/bar"
  152. block:
  153. let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"))
  154. doAssert concat.path == "/foo/test/bar/"
  155. block:
  156. let concat = combine(parseUri("http://google.com/foo/test/"), parseUri("bar/"),
  157. parseUri("baz"))
  158. doAssert concat.path == "/foo/test/bar/baz"
  159. block: # `/`
  160. block:
  161. let test = parseUri("http://example.com/foo") / "bar/asd"
  162. doAssert test.path == "/foo/bar/asd"
  163. block:
  164. let test = parseUri("http://example.com/foo/") / "/bar/asd"
  165. doAssert test.path == "/foo/bar/asd"
  166. block: # bug #3207
  167. doAssert parseUri("http://qq/1").combine(parseUri("https://qqq")).`$` == "https://qqq"
  168. block: # bug #4959
  169. let foo = parseUri("http://example.com") / "/baz"
  170. doAssert foo.path == "/baz"
  171. block: # bug found on stream 13/10/17
  172. let foo = parseUri("http://localhost:9515") / "status"
  173. doAssert $foo == "http://localhost:9515/status"
  174. block: # bug #6649 #6652
  175. var foo = parseUri("http://example.com")
  176. foo.hostname = "example.com"
  177. foo.path = "baz"
  178. doAssert $foo == "http://example.com/baz"
  179. foo.hostname = "example.com/"
  180. foo.path = "baz"
  181. doAssert $foo == "http://example.com/baz"
  182. foo.hostname = "example.com"
  183. foo.path = "/baz"
  184. doAssert $foo == "http://example.com/baz"
  185. foo.hostname = "example.com/"
  186. foo.path = "/baz"
  187. doAssert $foo == "http://example.com/baz"
  188. foo.hostname = "example.com/"
  189. foo.port = "8000"
  190. foo.path = "baz"
  191. doAssert $foo == "http://example.com:8000/baz"
  192. foo = parseUri("file:/dir/file")
  193. foo.path = "relative"
  194. doAssert $foo == "file:relative"
  195. block: # isAbsolute tests
  196. doAssert "www.google.com".parseUri().isAbsolute() == false
  197. doAssert "http://www.google.com".parseUri().isAbsolute() == true
  198. doAssert "file:/dir/file".parseUri().isAbsolute() == true
  199. doAssert "file://localhost/dir/file".parseUri().isAbsolute() == true
  200. doAssert "urn:ISSN:1535-3613".parseUri().isAbsolute() == true
  201. # path-relative URL *relative
  202. doAssert "about".parseUri().isAbsolute == false
  203. doAssert "about/staff.html".parseUri().isAbsolute == false
  204. doAssert "about/staff.html?".parseUri().isAbsolute == false
  205. doAssert "about/staff.html?parameters".parseUri().isAbsolute == false
  206. # absolute-path-relative URL *relative
  207. doAssert "/".parseUri().isAbsolute == false
  208. doAssert "/about".parseUri().isAbsolute == false
  209. doAssert "/about/staff.html".parseUri().isAbsolute == false
  210. doAssert "/about/staff.html?".parseUri().isAbsolute == false
  211. doAssert "/about/staff.html?parameters".parseUri().isAbsolute == false
  212. # scheme-relative URL *relative
  213. doAssert "//username:password@example.com:8888".parseUri().isAbsolute == false
  214. doAssert "//username@example.com".parseUri().isAbsolute == false
  215. doAssert "//example.com".parseUri().isAbsolute == false
  216. doAssert "//example.com/".parseUri().isAbsolute == false
  217. doAssert "//example.com/about".parseUri().isAbsolute == false
  218. doAssert "//example.com/about/staff.html".parseUri().isAbsolute == false
  219. doAssert "//example.com/about/staff.html?".parseUri().isAbsolute == false
  220. doAssert "//example.com/about/staff.html?parameters".parseUri().isAbsolute == false
  221. # absolute URL *absolute
  222. doAssert "https://username:password@example.com:8888".parseUri().isAbsolute == true
  223. doAssert "https://username@example.com".parseUri().isAbsolute == true
  224. doAssert "https://example.com".parseUri().isAbsolute == true
  225. doAssert "https://example.com/".parseUri().isAbsolute == true
  226. doAssert "https://example.com/about".parseUri().isAbsolute == true
  227. doAssert "https://example.com/about/staff.html".parseUri().isAbsolute == true
  228. doAssert "https://example.com/about/staff.html?".parseUri().isAbsolute == true
  229. doAssert "https://example.com/about/staff.html?parameters".parseUri().isAbsolute == true
  230. block: # encodeQuery tests
  231. doAssert encodeQuery({:}) == ""
  232. doAssert encodeQuery({"foo": "bar"}) == "foo=bar"
  233. doAssert encodeQuery({"foo": "bar & baz"}) == "foo=bar+%26+baz"
  234. doAssert encodeQuery({"foo": "bar & baz"}, usePlus = false) == "foo=bar%20%26%20baz"
  235. doAssert encodeQuery({"foo": ""}) == "foo"
  236. doAssert encodeQuery({"foo": ""}, omitEq = false) == "foo="
  237. doAssert encodeQuery({"a": "1", "b": "", "c": "3"}) == "a=1&b&c=3"
  238. doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, sep = ';') == "a=1;b;c=3"
  239. doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false) == "a=1&b=&c=3"
  240. doAssert encodeQuery({"a": "1", "b": "", "c": "3"}, omitEq = false, sep = ';') == "a=1;b=;c=3"
  241. block: # `?`
  242. block:
  243. var foo = parseUri("http://example.com") / "foo" ? {"bar": "1", "baz": "qux"}
  244. var foo1 = parseUri("http://example.com/foo?bar=1&baz=qux")
  245. doAssert foo == foo1
  246. block:
  247. var foo = parseUri("http://example.com") / "foo" ? {"do": "do", "bar": ""}
  248. var foo1 = parseUri("http://example.com/foo?do=do&bar")
  249. doAssert foo == foo1
  250. block: # getDataUri, dataUriBase64
  251. doAssert getDataUri("", "text/plain") == "data:text/plain;charset=utf-8;base64,"
  252. doAssert getDataUri(" ", "text/plain") == "data:text/plain;charset=utf-8;base64,IA=="
  253. doAssert getDataUri("c\xf7>", "text/plain") == "data:text/plain;charset=utf-8;base64,Y/c+"
  254. doAssert getDataUri("Hello World", "text/plain") == "data:text/plain;charset=utf-8;base64,SGVsbG8gV29ybGQ="
  255. doAssert getDataUri("leasure.", "text/plain") == "data:text/plain;charset=utf-8;base64,bGVhc3VyZS4="
  256. doAssert getDataUri("""!@#$%^&*()_+""", "text/plain") == "data:text/plain;charset=utf-8;base64,IUAjJCVeJiooKV8r"
  257. doAssert(getDataUri("the quick brown dog jumps over the lazy fox", "text/plain") ==
  258. "data:text/plain;charset=utf-8;base64,dGhlIHF1aWNrIGJyb3duIGRvZyBqdW1wcyBvdmVyIHRoZSBsYXp5IGZveA==")
  259. doAssert(getDataUri("The present is theirs\n The future, for which I really worked, is mine.", "text/plain") ==
  260. "data:text/plain;charset=utf-8;base64,VGhlIHByZXNlbnQgaXMgdGhlaXJzCiAgICAgIFRoZSBmdXR1cmUsIGZvciB3aGljaCBJIHJlYWxseSB3b3JrZWQsIGlzIG1pbmUu")
  261. block: # decodeQuery
  262. doAssert toSeq(decodeQuery("a=1&b=0")) == @[("a", "1"), ("b", "0")]
  263. doAssert toSeq(decodeQuery("a=1;b=0", sep = ';')) == @[("a", "1"), ("b", "0")]
  264. doAssert toSeq(decodeQuery("a=1&b=2c=6")) == @[("a", "1"), ("b", "2c=6")]
  265. doAssert toSeq(decodeQuery("a=1;b=2c=6", sep = ';')) == @[("a", "1"), ("b", "2c=6")]
  266. block: # bug #17481
  267. let u1 = parseUri("./")
  268. let u2 = parseUri("./path")
  269. let u3 = parseUri("a/path")
  270. doAssert u1.scheme.len == 0
  271. doAssert u1.path == "./"
  272. doAssert u2.scheme.len == 0
  273. doAssert u2.path == "./path"
  274. doAssert u3.scheme.len == 0
  275. doAssert u3.path == "a/path"
  276. static: main()
  277. main()