As opposed to the Connection-level API the host-level API relieves you from manually opening and closing each individual HTTP connection. It autonomously manages a configurable pool of connections to one particular server.
Starting an HttpHostConnector
The core of this API is the
HttpHostConnector actor, whose class, as with all other spray-can actors, you don’t
get in direct contact with from your application. All communication happens purely via actor messages, the majority of
which are defined in the spray.can.Http object.
You ask spray-can to start a new
HttpHostConnector for a given host by sending an
message to the
Http extension as such:
IO(Http) ! Http.HostConnectorSetup("www.spray.io", port = 80)
Apart from the host name and port the
Http.HostConnectorSetup message also allows you to specify socket options and
a larger number of configuration settings for the connector and the connections it is to manage.
If there is no connector actor running for the given combination of hostname, port and settings spray-can will start
a new one, otherwise the existing one is going to be re-used.
The connector will then respond with an
Http.HostConnectorInfo event message, which repeats the connectors
ActorRef and setup command (for easy matching against the result of an “ask”).
Using an HttpHostConnector
Once you’ve got a hold of the connectors
ActorRef you can send it one or more spray-http
messages. The connector will send the request across one of the connections it manages according to the following logic:
- if HTTP pipelining is not enabled (the default) the request is
- dispatched to the first idle connection in the pool if there is one
- dispatched to a newly opened connection if there is no idle one and less than the configured
max-connectionshave been opened so far
- queued and sent across the first connection that becomes available (i.e. either idle or unconnected) if all available connections are currently busy with open requests
- if HTTP pipelining is enabled the request is dispatched to
- the first idle connection in the pool if there is one
- a newly opened connection if there is no idle one and less than the configured
max-connectionshave been opened so far
- the connection with the least open requests if all connections already have requests open
As soon as a response for a request has been received it is dispatched as a
instance to the sender of the respective request. If the server indicated that it doesn’t want to reuse the connection
for other requests (either via a
Connection: close header on an
HTTP/1.1 response or a missing
Connection: Keep-Alive header on an
HTTP/1.0 response) the connector actor closes the connection after receipt
of the response thereby freeing up the “slot” for a new connection.
Retrying a Request
max-retries connector config setting is greater than zero the connector retries idempotent requests for which
a response could not be successfully retrieved. Idempotent requests are those whose HTTP method is defined to be
idempotent by the HTTP spec, which are all the ones currently modelled by spray-http except for the
When a response could not be received for a certain request there are essentially three possible error scenarios:
- The request got lost on the way to the server.
- The server experiences a problem while processing the request.
- The response from the server got lost on the way back.
Since the host connector cannot know which one of these possible reasons caused the problem and therefore
POST requests could have already triggered a non-idempotent action on the server these requests cannot be retried.
In these cases, as well as when all retries have not yielded a proper response, the connector dispatches a
Status.Failure message with a
RuntimeException holding a respective error message to the sender of the request.
The connector config contains an
idle-timeout setting which specifies the time period after which an idle connector,
i.e. one without any open connections, will automatically shut itself down. Since, by default, the connections in the
connectors connection pool also have an idle-timeout active an unused connector will eventually be cleaned up completely
if left unused.
However, in order to speed up the shutdown a host connector can be sent an
Http.CloseAll command, which
triggers an explicit closing of all connections. After all connections have been properly closed the connector will
Http.ClosedAll event message to all senders of
Http.CloseAll messages before stopping itself.
A subsequent sending of an identical
Http.HostConnectorSetup command to the
Http extension will then trigger the
creation of a fresh connector instance.