thttpclient.nim 5.7 KB

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