summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorEmery Hemingway <ehmry@posteo.net>2018-08-07 17:36:56 +0200
committerEmery Hemingway <ehmry@posteo.net>2018-08-08 07:48:24 +0200
commit817e4bb2fe0538a60f169d37e254b30e3dc3ab1d (patch)
treeaa57c10fb5fa8ed69a646f47323135ba8ea31b64
parent9b9cfa7306d696961cc6fd590ca72c08f66bdcb3 (diff)
downloadNim-817e4bb2fe0538a60f169d37e254b30e3dc3ab1d.tar.gz
AsyncHttpClient: return from requests before body completion
Store the body completion future at the client and wait for it to
complete before issuing additional requests. This allows the body
FutureStream reader to drain the stream and read buffers to be freed
asynchronously.

Fix #8109
-rw-r--r--lib/pure/httpclient.nim15
1 files changed, 13 insertions, 2 deletions
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 8b4fb0f8c..72de72718 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -807,6 +807,7 @@ type
     lastProgressReport: float
     when SocketType is AsyncSocket:
       bodyStream: FutureStream[string]
+      parseBodyFut: Future[void]
     else:
       bodyStream: Stream
     getBody: bool ## When `false`, the body is never read in requestAux.
@@ -1066,10 +1067,14 @@ proc parseResponse(client: HttpClient | AsyncHttpClient,
   if getBody:
     when client is HttpClient:
       client.bodyStream = newStringStream()
+      result.bodyStream = client.bodyStream
+      parseBody(client, result.headers, result.version)
     else:
       client.bodyStream = newFutureStream[string]("parseResponse")
-    await parseBody(client, result.headers, result.version)
-    result.bodyStream = client.bodyStream
+      result.bodyStream = client.bodyStream
+      assert(client.parseBodyFut.isNil or client.parseBodyFut.finished)
+      client.parseBodyFut = parseBody(client, result.headers, result.version)
+        # do not wait here for the body request to complete
 
 proc newConnection(client: HttpClient | AsyncHttpClient,
                    url: Uri) {.multisync.} =
@@ -1159,6 +1164,12 @@ proc requestAux(client: HttpClient | AsyncHttpClient, url: string,
   # Helper that actually makes the request. Does not handle redirects.
   let requestUrl = parseUri(url)
 
+  when client is AsyncHttpClient:
+    if not client.parseBodyFut.isNil:
+      # let the current operation finish before making another request
+      await client.parseBodyFut
+      client.parseBodyFut = nil
+
   await newConnection(client, requestUrl)
 
   let effectiveHeaders = client.headers.override(headers)