I don't even know why I try to understand things sometimes. Toying with adding 
pipelining support, I added some echo("OUT ", headersString) and echo("IN", 
line) to httpclient.nim to see what was actually being sent when. Then I ran 
this script:
    
    
    import asyncdispatch, asyncfutures, httpclient
    from strformat import `&`
    
    proc runclients() {.async.} =
      var futures: seq[Future[AsyncResponse]]
      let client = newAsyncHttpClient()
      for i in 0..5:
        let tag = &"{i}"
        echo("requesting to server ", tag)
        let f = (
          client.request(&"http://127.0.0.1/tag/{tag}";, "GET"))
        futures.add(f)
      
      try:
        let resps = await futures.all()
        for resp in resps:
          echo("response from server ", resp.headers)
        echo("getting bodies now")
        for resp in resps:
          discard await resp.body
        echo("done")
      except ProtocolError:
        echo("protocol error whee")
    waitFor runclients()
    
    
    Run

And it... hung until the socket timed out then died with a protocol error.

But! Looking at the IN and OUT stuff, I saw:
    
    
    OUT GET /tag/0 HTTP/1.1
    Host: 127.0.0.1
    Connection: Keep-Alive
    user-agent: Nim httpclient/0.20.99
    
    
    OUT GET /tag/1 HTTP/1.1
    Host: 127.0.0.1
    Connection: Keep-Alive
    user-agent: Nim httpclient/0.20.99
    
    
    OUT GET /tag/2 HTTP/1.1
    Host: 127.0.0.1
    Connection: Keep-Alive
    user-agent: Nim httpclient/0.20.99
    
    
    Run

and so on, and then ONLY after that, I saw 
    
    
    IN HTTP/1.1 404 Not Found
    IN Server: nginx/1.17.0
    IN Date: Sun, 09 Jun 2019 05:32:56 GMT
    etc
    
    
    Run

And that's uh... pipelining. So apparently when you wait for the entire 
response body, Nim just uses its psychic powers to determine that what you 
really want to do is send more requests while you're waiting. **httpclient.nim 
is doing HTTP pipelining just fine.**

As for why my script then hangs... it probably has to do with the fact that 
there hasn't been some joker yet, firing off a bunch of requests on one 
AsyncHttpClient before waiting for any of them to complete. All the data is 
successfully sent and received over the async socket, but httpclient.nim stalls 
out turning the response data into various AsyncHttpResponse objects. Probably 
naively overwriting a future or something, where a queue should be used instead.

Reply via email to