thttpclient.nim 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. discard """
  2. cmd: "nim c --threads:on -d:ssl $file"
  3. disabled: "openbsd"
  4. disabled: "freebsd"
  5. disabled: "windows"
  6. """
  7. #[
  8. disabled: see https://github.com/timotheecour/Nim/issues/528
  9. ]#
  10. import strutils
  11. from net import TimeoutError
  12. import nativesockets, os, httpclient, asyncdispatch
  13. import std/[assertions, syncio]
  14. const manualTests = false
  15. proc makeIPv6HttpServer(hostname: string, port: Port,
  16. message: string): AsyncFD =
  17. let fd = createNativeSocket(AF_INET6)
  18. setSockOptInt(fd, SOL_SOCKET, SO_REUSEADDR, 1)
  19. var aiList = getAddrInfo(hostname, port, AF_INET6)
  20. if bindAddr(fd, aiList.ai_addr, aiList.ai_addrlen.SockLen) < 0'i32:
  21. freeAddrInfo(aiList)
  22. raiseOSError(osLastError())
  23. freeAddrInfo(aiList)
  24. if listen(fd) != 0:
  25. raiseOSError(osLastError())
  26. setBlocking(fd, false)
  27. var serverFd = fd.AsyncFD
  28. register(serverFd)
  29. result = serverFd
  30. proc onAccept(fut: Future[AsyncFD]) {.gcsafe.} =
  31. if not fut.failed:
  32. let clientFd = fut.read()
  33. clientFd.send(message).callback = proc() =
  34. clientFd.closeSocket()
  35. serverFd.accept().callback = onAccept
  36. serverFd.accept().callback = onAccept
  37. proc asyncTest() {.async.} =
  38. var client = newAsyncHttpClient()
  39. var resp = await client.request("http://example.com/", HttpGet)
  40. doAssert(resp.code.is2xx)
  41. var body = await resp.body
  42. body = await resp.body # Test caching
  43. doAssert("<title>Example Domain</title>" in body)
  44. resp = await client.request("http://example.com/404")
  45. doAssert(resp.code.is4xx)
  46. doAssert(resp.code == Http404)
  47. doAssert(resp.status == $Http404)
  48. resp = await client.request("https://google.com/")
  49. doAssert(resp.code.is2xx or resp.code.is3xx)
  50. # getContent
  51. try:
  52. discard await client.getContent("https://google.com/404")
  53. doAssert(false, "HttpRequestError should have been raised")
  54. except HttpRequestError:
  55. discard
  56. except:
  57. doAssert(false, "HttpRequestError should have been raised")
  58. when false:
  59. # w3.org now blocks travis, so disabled:
  60. # Multipart test.
  61. var data = newMultipartData()
  62. data["output"] = "soap12"
  63. data["uploaded_file"] = ("test.html", "text/html",
  64. "<html><head></head><body><p>test</p></body></html>")
  65. resp = await client.post("http://validator.w3.org/check", multipart = data)
  66. doAssert(resp.code.is2xx)
  67. # onProgressChanged
  68. when manualTests:
  69. proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
  70. echo("Downloaded ", progress, " of ", total)
  71. echo("Current rate: ", speed div 1000, "kb/s")
  72. client.onProgressChanged = onProgressChanged
  73. await client.downloadFile("http://speedtest-ams2.digitalocean.com/100mb.test",
  74. "100mb.test")
  75. # HTTP/1.1 without Content-Length - issue #10726
  76. var serverFd = makeIPv6HttpServer("::1", Port(18473),
  77. "HTTP/1.1 200 \c\L" &
  78. "\c\L" &
  79. "Here comes reply")
  80. resp = await client.request("http://[::1]:18473/")
  81. body = await resp.body
  82. doAssert(body == "Here comes reply")
  83. serverFd.closeSocket()
  84. client.close()
  85. # Proxy test
  86. #when manualTests:
  87. # client = newAsyncHttpClient(proxy = newProxy("http://51.254.106.76:80/"))
  88. # var resp = await client.request("https://github.com")
  89. # echo resp
  90. proc syncTest() =
  91. var client = newHttpClient()
  92. var resp = client.request("http://example.com/", HttpGet)
  93. doAssert(resp.code.is2xx)
  94. doAssert("<title>Example Domain</title>" in resp.body)
  95. resp = client.request("http://example.com/404")
  96. doAssert(resp.code.is4xx)
  97. doAssert(resp.code == Http404)
  98. doAssert(resp.status == $Http404)
  99. resp = client.request("https://google.com/")
  100. doAssert(resp.code.is2xx or resp.code.is3xx)
  101. # getContent
  102. try:
  103. discard client.getContent("https://google.com/404")
  104. doAssert(false, "HttpRequestError should have been raised")
  105. except HttpRequestError:
  106. discard
  107. except:
  108. doAssert(false, "HttpRequestError should have been raised")
  109. when false:
  110. # w3.org now blocks travis, so disabled:
  111. # Multipart test.
  112. var data = newMultipartData()
  113. data["output"] = "soap12"
  114. data["uploaded_file"] = ("test.html", "text/html",
  115. "<html><head></head><body><p>test</p></body></html>")
  116. resp = client.post("http://validator.w3.org/check", multipart = data)
  117. doAssert(resp.code.is2xx)
  118. # onProgressChanged
  119. when manualTests:
  120. proc onProgressChanged(total, progress, speed: BiggestInt) =
  121. echo("Downloaded ", progress, " of ", total)
  122. echo("Current rate: ", speed div 1000, "kb/s")
  123. client.onProgressChanged = onProgressChanged
  124. client.downloadFile("http://speedtest-ams2.digitalocean.com/100mb.test",
  125. "100mb.test")
  126. client.close()
  127. # SIGSEGV on HEAD body read: issue #16743
  128. block:
  129. let client = newHttpClient()
  130. let resp = client.head("http://httpbin.org/head")
  131. doAssert(resp.body == "")
  132. when false:
  133. # Disabled for now because it causes troubles with AppVeyor
  134. # Timeout test.
  135. client = newHttpClient(timeout = 1)
  136. try:
  137. resp = client.request("http://example.com/")
  138. doAssert false, "TimeoutError should have been raised."
  139. except TimeoutError:
  140. discard
  141. except:
  142. doAssert false, "TimeoutError should have been raised."
  143. proc ipv6Test() =
  144. var client = newAsyncHttpClient()
  145. let serverFd = makeIPv6HttpServer("::1", Port(18473),
  146. "HTTP/1.1 200 OK\r\LContent-Length: 0\r\LConnection: Closed\r\L\r\L")
  147. var resp = waitFor client.request("http://[::1]:18473/")
  148. doAssert(resp.status == "200 OK")
  149. serverFd.closeSocket()
  150. client.close()
  151. ipv6Test()
  152. syncTest()
  153. waitFor(asyncTest())