Examples and docs say:
- Create a HTTPClient "A client should create one instance of this class."[0]
- Create a Payload
- Create a HandlerMaker
- Call client.apply(payload, handlermaker)
apply(..)
creates the TCP connection and enables TLS as appropriate; wrapping the handler (created by the provided HandlerMaker
) in a _ClientConnection
which is the HTTPSession
.
The client then caches this HTTPSession against the (scheme, host, port) tuple.
Now, we have a Map in the HTTPClient
from (scheme, host, port) ==> (tcp_connection, response_handler)
The first request goes through and is handled happily by the response handler.
Now we want to make another call to the same http service; but with a different path/parameters.
We create a Payload, and a different HandlerMaker
- we want to do something different with the result of the second call as the data that is returned is completely different.
Trigger the request by calling client.apply(new_payload, new_handler_maker)
The client then notes the there is a mapping for the existing (scheme, host, port)
tuple and reuses the session from before. This is a mostly a good thing as we now do not need to re-setup a TLS connection, removing one of the notable https performance overheads, HOWEVER, it also re-uses the response_handler for the FIRST request as it has not touched the new_handler_maker
at all.
Given the code attached, this produces an infinite loop; as it makes the request for the second request, but calls the callback for the first request; causing the second request to be re-made, and never calling _Runner.run(...)
.
- in the handler (or somewhere), maintain a map/stack/? of Payload URLs and resolve the correct handler when the response is received. This is suboptimal as I predict there will be a whole load of data races as adding things to the various actors' state can happen out-of-order
- create a new
HTTPClient
for every request, and therefore negate the connection re-use advantage. - re-instate the handler field in the Payload class, and get the
_Responder
to call it when it's done.
All the examples that I've seen are either prior to the change [1] in net/http or only make one http request and then exit [1,2].