2014-07-06 13:10:35 +02:00
|
|
|
::: The life of a request
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
This chapter explains the different steps a request
|
|
|
|
goes through until a response is sent, along with
|
|
|
|
details of the Cowboy implementation.
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
:: Request/response
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
As you already know, HTTP clients connect to the server and
|
|
|
|
send a request for a resource; the server then sends a
|
|
|
|
response containing the resource if it could obtain it.
|
|
|
|
|
|
|
|
Before the server can send the resource, however, it
|
|
|
|
needs to perform many different operations to read the
|
|
|
|
request, find the resource, prepare the response being
|
|
|
|
sent and often other related operations the user can
|
|
|
|
add like writing logs.
|
|
|
|
|
|
|
|
Requests take the following route in Cowboy:
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
^"HTTP request/response flowchart^!http_req_resp.png
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
This shows the default middlewares, but they may be
|
|
|
|
configured differently in your setup. The dark green
|
|
|
|
indicates the points where you can hook your own code,
|
|
|
|
the light green is the Cowboy code that you can of
|
|
|
|
course configure as needed.
|
|
|
|
|
|
|
|
The `acceptor` is the part of the server that accepts
|
|
|
|
the connection and create an Erlang process to handle
|
|
|
|
it. The `parser` then starts reading from the socket
|
|
|
|
and handling requests as they come until the socket
|
|
|
|
is closed.
|
|
|
|
|
|
|
|
A response may be sent at many different points in the
|
|
|
|
life of the request. If Cowboy can't parse the request,
|
|
|
|
it gives up with an error response. If the router can't
|
|
|
|
find the resource, it sends a not found error. Your
|
|
|
|
own code can of course send a response at any time.
|
|
|
|
|
|
|
|
When a response is sent, you can optionally modify it
|
|
|
|
or act upon it by enabling the `onresponse` hook. By
|
|
|
|
default the response is sent directly to the client.
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
:: And then?
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
Behavior depends on what protocol is in use.
|
|
|
|
|
|
|
|
HTTP/1.0 can only process one request per connection,
|
|
|
|
so Cowboy will close the connection immediately after
|
|
|
|
it sends the response.
|
|
|
|
|
|
|
|
HTTP/1.1 allows the client to request that the server
|
|
|
|
keeps the connection alive. This mechanism is described
|
|
|
|
in the next section.
|
|
|
|
|
|
|
|
SPDY is designed to allow sending multiple requests
|
|
|
|
asynchronously on the same connection. Details on what
|
|
|
|
this means for your application is described in this
|
|
|
|
chapter.
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
:: Keep-alive (HTTP/1.1)
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
With HTTP/1.1, the connection may be left open for
|
|
|
|
subsequent requests to come. This mechanism is called
|
|
|
|
`keep-alive`.
|
|
|
|
|
|
|
|
When the client sends a request to the server, it includes
|
|
|
|
a header indicating whether it would like to leave the
|
|
|
|
socket open. The server may or may not accept, indicating
|
|
|
|
its choice by sending the same header in the response.
|
|
|
|
|
|
|
|
Cowboy will include this header automatically in all
|
|
|
|
responses to HTTP/1.1 requests. You can however force
|
|
|
|
the closing of the socket if you want. When Cowboy sees
|
|
|
|
you want to send a `connection: close` header, it will
|
|
|
|
not override it and will close the connection as soon
|
|
|
|
as the reply is sent.
|
|
|
|
|
|
|
|
This snippet will force Cowboy to close the connection.
|
|
|
|
|
|
|
|
``` erlang
|
|
|
|
{ok, Req2} = cowboy_req:reply(200, [
|
|
|
|
{<<"connection">>, <<"close">>},
|
|
|
|
], <<"Closing the socket in 3.. 2.. 1..">>, Req).
|
|
|
|
```
|
|
|
|
|
|
|
|
Cowboy will only accept a certain number of new requests
|
|
|
|
on the same connection. By default it will run up to 100
|
|
|
|
requests. This number can be changed by setting the
|
|
|
|
`max_keepalive` configuration value when starting an
|
|
|
|
HTTP listener.
|
|
|
|
|
|
|
|
``` erlang
|
|
|
|
cowboy:start_http(my_http_listener, 100, [{port, 8080}], [
|
|
|
|
{env, [{dispatch, Dispatch}]},
|
|
|
|
{max_keepalive, 5}
|
|
|
|
]).
|
|
|
|
```
|
|
|
|
|
|
|
|
Cowboy implements the keep-alive mechanism by reusing
|
|
|
|
the same process for all requests. This allows Cowboy
|
|
|
|
to save memory. This works well because most code will
|
|
|
|
not have any side effect impacting subsequent requests.
|
|
|
|
But it also means you need to clean up if you do have
|
|
|
|
code with side effects. The `terminate/3` function can
|
|
|
|
be used for this purpose.
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
:: Pipelining (HTTP/1.1)
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
While HTTP is designed as a sequential protocol, with
|
|
|
|
the client sending a request and then waiting for the
|
|
|
|
response from the server, nothing prevents the client
|
|
|
|
from sending more requests to the server without waiting
|
|
|
|
for the response, due to how sockets work. The server
|
|
|
|
still handles the requests sequentially and sends the
|
|
|
|
responses in the same order.
|
|
|
|
|
|
|
|
This mechanism is called pipelining. It allows reducing
|
|
|
|
latency when a client needs to request many resources
|
|
|
|
at the same time. This is used by browsers when requesting
|
|
|
|
static files for example.
|
|
|
|
|
|
|
|
This is handled automatically by the server.
|
|
|
|
|
2014-07-06 13:10:35 +02:00
|
|
|
:: Asynchronous requests (SPDY)
|
2013-09-16 23:51:09 +02:00
|
|
|
|
|
|
|
In SPDY, the client can send a request at any time.
|
|
|
|
And the server can send a response at any time too.
|
|
|
|
|
|
|
|
This means for example that the client does not need
|
|
|
|
to wait for a request to be fully sent to send another,
|
|
|
|
it is possible to interleave a request with the request
|
|
|
|
body of another request. The same is true with responses.
|
|
|
|
Responses may also be sent in a different order.
|
|
|
|
|
|
|
|
Because requests and responses are fully asynchronous,
|
|
|
|
Cowboy creates a new process for each request, and these
|
|
|
|
processes are managed by another process that handles the
|
|
|
|
connection itself.
|
|
|
|
|
|
|
|
SPDY servers may also decide to send resources to the
|
|
|
|
client before the client requests them. This is especially
|
|
|
|
useful for sending static files associated with the HTML
|
|
|
|
page requested, as this reduces the latency of the overall
|
|
|
|
response. Cowboy does not support this particular mechanism
|
|
|
|
at this point, however.
|