mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Wrap-up the user guide
This commit is contained in:
parent
642630fea1
commit
fd3c40c7ee
11 changed files with 291 additions and 209 deletions
|
@ -1,33 +1,18 @@
|
||||||
Internals
|
|
||||||
=========
|
|
||||||
|
|
||||||
Architecture
|
Architecture
|
||||||
------------
|
============
|
||||||
|
|
||||||
Cowboy is a lightweight HTTP server.
|
Cowboy is a lightweight HTTP server.
|
||||||
|
|
||||||
It is built on top of Ranch. Please see the Ranch guide for more
|
It is built on top of Ranch. Please see the Ranch guide for more
|
||||||
informations.
|
information.
|
||||||
|
|
||||||
|
One process per connection
|
||||||
|
--------------------------
|
||||||
|
|
||||||
It uses only one process per connection. The process where your
|
It uses only one process per connection. The process where your
|
||||||
code runs is the process controlling the socket. Using one process
|
code runs is the process controlling the socket. Using one process
|
||||||
instead of two allows for lower memory usage.
|
instead of two allows for lower memory usage.
|
||||||
|
|
||||||
It uses binaries. Binaries are more efficient than lists for
|
|
||||||
representing strings because they take less memory space. Processing
|
|
||||||
performance can vary depending on the operation. Binaries are known
|
|
||||||
for generally getting a great boost if the code is compiled natively.
|
|
||||||
Please see the HiPE documentation for more details.
|
|
||||||
|
|
||||||
Because querying for the current date and time can be expensive,
|
|
||||||
Cowboy generates one `Date` header value every second, shares it
|
|
||||||
to all other processes, which then simply copy it in the response.
|
|
||||||
This allows compliance with HTTP/1.1 with no actual performance loss.
|
|
||||||
|
|
||||||
One process for many requests
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
As previously mentioned, Cowboy only use one process per connection.
|
|
||||||
Because there can be more than one request per connection with the
|
Because there can be more than one request per connection with the
|
||||||
keepalive feature of HTTP/1.1, that means the same process will be
|
keepalive feature of HTTP/1.1, that means the same process will be
|
||||||
used to handle many requests.
|
used to handle many requests.
|
||||||
|
@ -37,32 +22,25 @@ up before terminating the handling of the current request. This may
|
||||||
include cleaning up the process dictionary, timers, monitoring and
|
include cleaning up the process dictionary, timers, monitoring and
|
||||||
more.
|
more.
|
||||||
|
|
||||||
Lowercase header names
|
Binaries
|
||||||
----------------------
|
--------
|
||||||
|
|
||||||
For consistency reasons it has been chosen to convert all header names
|
It uses binaries. Binaries are more efficient than lists for
|
||||||
to lowercase binary strings. This prevents the programmer from making
|
representing strings because they take less memory space. Processing
|
||||||
case mistakes, and is possible because header names are case insensitive.
|
performance can vary depending on the operation. Binaries are known
|
||||||
|
for generally getting a great boost if the code is compiled natively.
|
||||||
|
Please see the HiPE documentation for more details.
|
||||||
|
|
||||||
This works fine for the large majority of clients. However, some badly
|
Date header
|
||||||
implemented clients, especially ones found in corporate code or closed
|
-----------
|
||||||
source products, may not handle header names in a case insensitive manner.
|
|
||||||
This means that when Cowboy returns lowercase header names, these clients
|
|
||||||
will not find the headers they are looking for.
|
|
||||||
|
|
||||||
A simple way to solve this is to create an `onresponse` hook that will
|
Because querying for the current date and time can be expensive,
|
||||||
format the header names with the expected case.
|
Cowboy generates one `Date` header value every second, shares it
|
||||||
|
to all other processes, which then simply copy it in the response.
|
||||||
|
This allows compliance with HTTP/1.1 with no actual performance loss.
|
||||||
|
|
||||||
``` erlang
|
Max connections
|
||||||
capitalize_hook(Status, Headers, Body, Req) ->
|
---------------
|
||||||
Headers2 = [{cowboy_bstr:capitalize_token(N), V}
|
|
||||||
|| {N, V} <- Headers],
|
|
||||||
{ok, Req2} = cowboy_req:reply(Status, Headers2, Body, Req),
|
|
||||||
Req2.
|
|
||||||
```
|
|
||||||
|
|
||||||
Improving performance
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
By default the maximum number of active connections is set to a
|
By default the maximum number of active connections is set to a
|
||||||
generally accepted big enough number. This is meant to prevent having
|
generally accepted big enough number. This is meant to prevent having
|
||||||
|
@ -72,8 +50,3 @@ everything else down, or taking up all the memory.
|
||||||
Disabling this feature, by setting the `{max_connections, infinity}`
|
Disabling this feature, by setting the `{max_connections, infinity}`
|
||||||
protocol option, would give you greater performance when you are
|
protocol option, would give you greater performance when you are
|
||||||
only processing short-lived requests.
|
only processing short-lived requests.
|
||||||
|
|
||||||
Another option is to define platform-specific socket options that
|
|
||||||
are known to improve their efficiency.
|
|
||||||
|
|
||||||
Please see the Ranch guide for more information.
|
|
65
guide/broken_clients.md
Normal file
65
guide/broken_clients.md
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
Dealing with broken clients
|
||||||
|
===========================
|
||||||
|
|
||||||
|
There exists a very large number of implementations for the
|
||||||
|
HTTP protocol. Most widely used clients, like browsers,
|
||||||
|
follow the standard quite well, but others may not. In
|
||||||
|
particular custom enterprise clients tend to be very badly
|
||||||
|
written.
|
||||||
|
|
||||||
|
Cowboy tries to follow the standard as much as possible,
|
||||||
|
but is not trying to handle very possible special cases.
|
||||||
|
Instead Cowboy focuses on the cases reported in the wild,
|
||||||
|
on the public Web.
|
||||||
|
|
||||||
|
That means clients that ignore the HTTP standard completely
|
||||||
|
may fail to understand Cowboy's responses. There are of
|
||||||
|
course workarounds. This chapter aims to cover them.
|
||||||
|
|
||||||
|
Lowercase headers
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Cowboy converts all headers it receives to lowercase, and
|
||||||
|
similarly sends back headers all in lowercase. Some broken
|
||||||
|
HTTP clients have issues with that.
|
||||||
|
|
||||||
|
A simple way to solve this is to create an `onresponse` hook
|
||||||
|
that will format the header names with the expected case.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
|
capitalize_hook(Status, Headers, Body, Req) ->
|
||||||
|
Headers2 = [{cowboy_bstr:capitalize_token(N), V}
|
||||||
|
|| {N, V} <- Headers],
|
||||||
|
{ok, Req2} = cowboy_req:reply(Status, Headers2, Body, Req),
|
||||||
|
Req2.
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that SPDY clients do not have that particular issue
|
||||||
|
because the specification explicitly says all headers are
|
||||||
|
lowercase, unlike HTTP which allows any case but treats
|
||||||
|
them as case insensitive.
|
||||||
|
|
||||||
|
Camel-case headers
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Sometimes it is desirable to keep the actual case used by
|
||||||
|
clients, for example when acting as a proxy between two broken
|
||||||
|
implementations. There is no easy solution for this other than
|
||||||
|
forking the project and editing the `cowboy_protocol` file
|
||||||
|
directly.
|
||||||
|
|
||||||
|
Chunked transfer-encoding
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Sometimes an HTTP client advertises itself as HTTP/1.1 but
|
||||||
|
does not support chunked transfer-encoding. This is invalid
|
||||||
|
behavior, as HTTP/1.1 clients are required to support it.
|
||||||
|
|
||||||
|
A simple workaround exists in these cases. By changing the
|
||||||
|
Req object response state to `waiting_stream`, Cowboy will
|
||||||
|
understand that it must use the identity transfer-encoding
|
||||||
|
when replying, just like if it was an HTTP/1.0 client.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
|
Req2 = cowboy_req:set(resp_state, waiting_stream).
|
||||||
|
```
|
|
@ -1,21 +1,20 @@
|
||||||
Getting started
|
Getting started
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Setting up a working Erlang application is a little more complex than
|
Erlang is more than a language, it is also an operating system
|
||||||
for most other languages. The reason is that Erlang is designed to
|
for your applications. Erlang developers rarely write standalone
|
||||||
build systems and not just simple applications.
|
modules, they write libraries or applications, and then bundle
|
||||||
|
those into what is called a release. A release contains the
|
||||||
|
Erlang VM plus all applications required to run the node, so
|
||||||
|
it can be pushed to production directly.
|
||||||
|
|
||||||
An Erlang system is typically comprised of many different nodes,
|
This chapter walks you through all the steps of setting up
|
||||||
each containing many different OTP applications, each containing
|
Cowboy, writing your first application and generating your first
|
||||||
many different modules and running many different processes.
|
release. At the end of this chapter you should know everything
|
||||||
Nodes may or may not be identical depending on the nature of the
|
you need to push your first Cowboy application to production.
|
||||||
system.
|
|
||||||
|
|
||||||
To get started though, we only need one node that contains your own
|
Application skeleton
|
||||||
HTTP application, plus the dependencies that it needs, like Cowboy.
|
--------------------
|
||||||
To create our node, we need to build what is called a release. A
|
|
||||||
release is a set of files that contain the Erlang VM plus all the
|
|
||||||
applications required to run our node.
|
|
||||||
|
|
||||||
Let's start by creating this application. We will simply call it
|
Let's start by creating this application. We will simply call it
|
||||||
`hello_erlang`. This application will have the following directory
|
`hello_erlang`. This application will have the following directory
|
||||||
|
@ -130,6 +129,9 @@ That's not enough however. Since we are building a Cowboy based
|
||||||
application, we also need to initialize Cowboy when we start our
|
application, we also need to initialize Cowboy when we start our
|
||||||
application.
|
application.
|
||||||
|
|
||||||
|
Setting up Cowboy
|
||||||
|
-----------------
|
||||||
|
|
||||||
Cowboy does nothing by default.
|
Cowboy does nothing by default.
|
||||||
|
|
||||||
Cowboy uses Ranch for handling the connections and provides convenience
|
Cowboy uses Ranch for handling the connections and provides convenience
|
||||||
|
@ -198,6 +200,9 @@ init([]) ->
|
||||||
|
|
||||||
Finally, we need to write the code for handling incoming requests.
|
Finally, we need to write the code for handling incoming requests.
|
||||||
|
|
||||||
|
Handling HTTP requests
|
||||||
|
----------------------
|
||||||
|
|
||||||
Cowboy features many kinds of handlers. For this simple example,
|
Cowboy features many kinds of handlers. For this simple example,
|
||||||
we will just use the plain HTTP handler, which has three callback
|
we will just use the plain HTTP handler, which has three callback
|
||||||
functions: `init/3`, `handle/2` and `terminate/3`. You can find more
|
functions: `init/3`, `handle/2` and `terminate/3`. You can find more
|
||||||
|
@ -235,6 +240,9 @@ Its usage is documented in the
|
||||||
|
|
||||||
The code for our application is ready, so let's build a release!
|
The code for our application is ready, so let's build a release!
|
||||||
|
|
||||||
|
Compiling
|
||||||
|
---------
|
||||||
|
|
||||||
First we need to download `erlang.mk`.
|
First we need to download `erlang.mk`.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
|
@ -271,6 +279,9 @@ haven't made any typo when creating the previous files.
|
||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Generating the release
|
||||||
|
----------------------
|
||||||
|
|
||||||
That's not all however, as we want to create a working release.
|
That's not all however, as we want to create a working release.
|
||||||
For that purpose, we need to create a `relx.config` file. When
|
For that purpose, we need to create a `relx.config` file. When
|
||||||
this file exists, `erlang.mk` will automatically download `relx`
|
this file exists, `erlang.mk` will automatically download `relx`
|
||||||
|
@ -299,6 +310,3 @@ $ ./_rel/bin/hello_erlang console
|
||||||
|
|
||||||
If you then access `http://localhost:8080` using your browser,
|
If you then access `http://localhost:8080` using your browser,
|
||||||
you should receive a nice greet!
|
you should receive a nice greet!
|
||||||
|
|
||||||
You can find many more examples in the `examples/` directory
|
|
||||||
of the Cowboy repository.
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
Handlers
|
|
||||||
========
|
|
||||||
|
|
||||||
Purpose
|
|
||||||
-------
|
|
||||||
|
|
||||||
Handlers are Erlang modules that represent a resource.
|
|
||||||
|
|
||||||
Handlers must process the request and send a reply. The nature of the
|
|
||||||
reply will vary between handlers.
|
|
||||||
|
|
||||||
Different kinds of handlers can be combined in a single module. This
|
|
||||||
allows a module to handle both websocket and long-polling code in a
|
|
||||||
single place, for example.
|
|
||||||
|
|
||||||
Protocol upgrades
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Cowboy features many different handlers: HTTP handlers, loop handlers,
|
|
||||||
websocket handlers, REST handlers and static handlers. All of them
|
|
||||||
have a common entry point: the `init/3` function.
|
|
||||||
|
|
||||||
By default, Cowboy considers your handler to be an HTTP handler.
|
|
||||||
|
|
||||||
To switch to a different protocol, like, for example, Websocket,
|
|
||||||
you must perform a protocol upgrade. This is done by returning
|
|
||||||
a protocol upgrade tuple at the end of `init/3`.
|
|
||||||
|
|
||||||
The following snippet upgrades the handler to `my_protocol`.
|
|
||||||
|
|
||||||
``` erlang
|
|
||||||
init(_Any, _Req, _Opts) ->
|
|
||||||
{upgrade, protocol, my_protocol}.
|
|
||||||
```
|
|
||||||
|
|
||||||
Cowboy comes with two protocol upgrades: `cowboy_rest` and
|
|
||||||
`cowboy_websocket`. Use these values in place of `my_protocol`
|
|
||||||
to use them.
|
|
||||||
|
|
||||||
Custom protocol upgrades
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
The `my_protocol` module above will be used for further processing
|
|
||||||
of the request. It should use the `cowboy_sub_protocol` behaviour,
|
|
||||||
which requires only one callback, `upgrade/4`.
|
|
||||||
|
|
||||||
It receives the request object, the middleware environment, and
|
|
||||||
the handler this request has been routed to along with its options.
|
|
||||||
|
|
||||||
``` erlang
|
|
||||||
upgrade(Req, Env, Handler, HandlerOpts) ->
|
|
||||||
%% ...
|
|
||||||
```
|
|
||||||
|
|
||||||
This callback is expected to behave like any middleware. Please
|
|
||||||
see the corresponding chapter for more information.
|
|
|
@ -1,8 +1,12 @@
|
||||||
Hooks
|
Hooks
|
||||||
=====
|
=====
|
||||||
|
|
||||||
On request
|
Cowboy provides two hooks. `onrequest` is called once the request
|
||||||
----------
|
line and headers have been received. `onresponse` is called just
|
||||||
|
before sending the response.
|
||||||
|
|
||||||
|
Onrequest
|
||||||
|
---------
|
||||||
|
|
||||||
The `onrequest` hook is called as soon as Cowboy finishes fetching
|
The `onrequest` hook is called as soon as Cowboy finishes fetching
|
||||||
the request headers. It occurs before any other processing, including
|
the request headers. It occurs before any other processing, including
|
||||||
|
@ -39,8 +43,8 @@ debug_hook(Req) ->
|
||||||
|
|
||||||
Make sure to always return the last request object obtained.
|
Make sure to always return the last request object obtained.
|
||||||
|
|
||||||
On response
|
Onresponse
|
||||||
-----------
|
----------
|
||||||
|
|
||||||
The `onresponse` hook is called right before sending the response
|
The `onresponse` hook is called right before sending the response
|
||||||
to the socket. It can be used for the purposes of logging responses,
|
to the socket. It can be used for the purposes of logging responses,
|
||||||
|
@ -51,7 +55,7 @@ Note that like the `onrequest` hook, this function MUST NOT crash.
|
||||||
Cowboy may or may not send a reply if this function crashes. If a reply
|
Cowboy may or may not send a reply if this function crashes. If a reply
|
||||||
is sent, the hook MUST explicitly provide all headers that are needed.
|
is sent, the hook MUST explicitly provide all headers that are needed.
|
||||||
|
|
||||||
You can specify the `onresponse` hook when creating the listener also.
|
You can specify the `onresponse` hook when creating the listener.
|
||||||
|
|
||||||
``` erlang
|
``` erlang
|
||||||
cowboy:start_http(my_http_listener, 100,
|
cowboy:start_http(my_http_listener, 100,
|
||||||
|
|
|
@ -1,24 +1,11 @@
|
||||||
Loop handlers
|
Loop handlers
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Purpose
|
|
||||||
-------
|
|
||||||
|
|
||||||
Loop handlers are a special kind of HTTP handlers used when the
|
Loop handlers are a special kind of HTTP handlers used when the
|
||||||
response can not be sent right away. The handler enters instead
|
response can not be sent right away. The handler enters instead
|
||||||
a receive loop waiting for the right message before it can send
|
a receive loop waiting for the right message before it can send
|
||||||
a response.
|
a response.
|
||||||
|
|
||||||
They are most useful when performing long-polling operations or
|
|
||||||
when using server-sent events.
|
|
||||||
|
|
||||||
While the same can be accomplished using plain HTTP handlers,
|
|
||||||
it is recommended to use loop handlers because they are well-tested
|
|
||||||
and allow using built-in features like hibernation and timeouts.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
Loop handlers are used for requests where a response might not
|
Loop handlers are used for requests where a response might not
|
||||||
be immediately available, but where you would like to keep the
|
be immediately available, but where you would like to keep the
|
||||||
connection open for a while in case the response arrives. The
|
connection open for a while in case the response arrives. The
|
||||||
|
@ -29,34 +16,133 @@ partially available and you need to stream the response body
|
||||||
while the connection is open. The most known example of such
|
while the connection is open. The most known example of such
|
||||||
practice is known as server-sent events.
|
practice is known as server-sent events.
|
||||||
|
|
||||||
|
While the same can be accomplished using plain HTTP handlers,
|
||||||
|
it is recommended to use loop handlers because they are well-tested
|
||||||
|
and allow using built-in features like hibernation and timeouts.
|
||||||
|
|
||||||
Loop handlers essentially wait for one or more Erlang messages
|
Loop handlers essentially wait for one or more Erlang messages
|
||||||
and feed these messages to the `info/3` callback. It also features
|
and feed these messages to the `info/3` callback. It also features
|
||||||
the `init/3` and `terminate/3` callbacks which work the same as
|
the `init/3` and `terminate/3` callbacks which work the same as
|
||||||
for plain HTTP handlers.
|
for plain HTTP handlers.
|
||||||
|
|
||||||
The following handler waits for a message `{reply, Body}` before
|
Initialization
|
||||||
sending a response. If this message doesn't arrive within 60
|
--------------
|
||||||
seconds, it gives up and a `204 No Content` will be replied.
|
|
||||||
It also hibernates the process to save memory while waiting for
|
The `init/3` function must return a `loop` tuple to enable
|
||||||
this message.
|
loop handler behavior. This tuple may optionally contain
|
||||||
|
a timeout value and/or the atom `hibernate` to make the
|
||||||
|
process enter hibernation until a message is received.
|
||||||
|
|
||||||
|
This snippet enables the loop handler.
|
||||||
|
|
||||||
``` erlang
|
``` erlang
|
||||||
-module(my_loop_handler).
|
init(_Type, Req, _Opts) ->
|
||||||
-behaviour(cowboy_loop_handler).
|
{loop, Req, undefined_state}.
|
||||||
|
```
|
||||||
|
|
||||||
-export([init/3]).
|
However it is largely recommended that you set a timeout
|
||||||
-export([info/3]).
|
value. The next example sets a timeout value of 30s and
|
||||||
-export([terminate/3]).
|
also makes the process hibernate.
|
||||||
|
|
||||||
init({tcp, http}, Req, Opts) ->
|
``` erlang
|
||||||
{loop, Req, undefined_state, 60000, hibernate}.
|
init(_Type, Req, _Opts) ->
|
||||||
|
{loop, Req, undefined_state, 30000, hibernate}.
|
||||||
|
```
|
||||||
|
|
||||||
|
Receive loop
|
||||||
|
------------
|
||||||
|
|
||||||
|
Once initialized, Cowboy will wait for messages to arrive
|
||||||
|
in the process' mailbox. When a message arrives, Cowboy
|
||||||
|
calls the `info/3` function with the message, the Req object
|
||||||
|
and the handler's state.
|
||||||
|
|
||||||
|
The following snippet sends a reply when it receives a
|
||||||
|
`reply` message from another process, or waits for another
|
||||||
|
message otherwise.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
info({reply, Body}, Req, State) ->
|
info({reply, Body}, Req, State) ->
|
||||||
{ok, Req2} = cowboy_req:reply(200, [], Body, Req),
|
{ok, Req2} = cowboy_req:reply(200, [], Body, Req),
|
||||||
{ok, Req2, State};
|
{ok, Req2, State};
|
||||||
info(Message, Req, State) ->
|
info(_Msg, Req, State) ->
|
||||||
{loop, Req, State, hibernate}.
|
{loop, Req, State, hibernate}.
|
||||||
|
|
||||||
terminate(Reason, Req, State) ->
|
|
||||||
ok.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Do note that the `reply` tuple here may be any message
|
||||||
|
and is simply an example.
|
||||||
|
|
||||||
|
This callback may perform any necessary operation including
|
||||||
|
sending all or parts of a reply, and will subsequently
|
||||||
|
return a tuple indicating if more messages are to be expected.
|
||||||
|
|
||||||
|
The callback may also choose to do nothing at all and just
|
||||||
|
skip the message received.
|
||||||
|
|
||||||
|
If a reply is sent, then the `ok` tuple should be returned.
|
||||||
|
This will instruct Cowboy to end the request.
|
||||||
|
|
||||||
|
Otherwise a `loop` tuple should be returned.
|
||||||
|
|
||||||
|
Streaming loop
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Another common case well suited for loop handlers is
|
||||||
|
streaming data received in the form of Erlang messages.
|
||||||
|
This can be done by initiating a chunked reply in the
|
||||||
|
`init/3` callback and then using `cowboy_req:chunk/2`
|
||||||
|
every time a message is received.
|
||||||
|
|
||||||
|
The following snippet does exactly that. As you can see
|
||||||
|
a chunk is sent every time a `chunk` message is received,
|
||||||
|
and the loop is stopped by sending an `eof` message.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
|
init(_Type, Req, _Opts) ->
|
||||||
|
{ok, Req2} = cowboy_req:chunked_reply(200, [], Req),
|
||||||
|
{loop, Req2, undefined_state}.
|
||||||
|
|
||||||
|
info(eof, Req, State) ->
|
||||||
|
{ok, Req, State};
|
||||||
|
info({chunk, Chunk}, Req, State) ->
|
||||||
|
ok = cowboy_req:chunk(Chunk, Req),
|
||||||
|
{loop, Req, State};
|
||||||
|
info(_Msg, Req, State) ->
|
||||||
|
{loop, Req, State}.
|
||||||
|
```
|
||||||
|
|
||||||
|
Cleaning up
|
||||||
|
-----------
|
||||||
|
|
||||||
|
It is recommended that you set the connection header to
|
||||||
|
`close` when replying, as this process may be reused for
|
||||||
|
a subsequent request.
|
||||||
|
|
||||||
|
Please refer to the [HTTP handlers chapter](http_handlers.md)
|
||||||
|
for general instructions about cleaning up.
|
||||||
|
|
||||||
|
Timeout
|
||||||
|
-------
|
||||||
|
|
||||||
|
By default Cowboy will not attempt to close the connection
|
||||||
|
if there is no activity from the client. This is not always
|
||||||
|
desirable, which is why you can set a timeout. Cowboy will
|
||||||
|
close the connection if no data was received from the client
|
||||||
|
after the configured time. The timeout only needs to be set
|
||||||
|
once and can't be modified afterwards.
|
||||||
|
|
||||||
|
Because the request may have had a body, or may be followed
|
||||||
|
by another request, Cowboy is forced to buffer all data it
|
||||||
|
receives. This data may grow to become too large though,
|
||||||
|
so there is a configurable limit for it. The default buffer
|
||||||
|
size is of 5000 bytes, but it may be changed by setting the
|
||||||
|
`loop_max_buffer` middleware environment value.
|
||||||
|
|
||||||
|
Hibernate
|
||||||
|
---------
|
||||||
|
|
||||||
|
To save memory, you may hibernate the process in between
|
||||||
|
messages received. This is done by returning the atom
|
||||||
|
`hibernate` as part of the `loop` tuple callbacks normally
|
||||||
|
return. Just add the atom at the end and Cowboy will hibernate
|
||||||
|
accordingly.
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
Middlewares
|
Middlewares
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Purpose
|
|
||||||
-------
|
|
||||||
|
|
||||||
Cowboy delegates the request processing to middleware components.
|
Cowboy delegates the request processing to middleware components.
|
||||||
By default, two middlewares are defined, for the routing and handling
|
By default, two middlewares are defined, for the routing and handling
|
||||||
of the request, as is detailed in most of this guide.
|
of the request, as is detailed in most of this guide.
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
Resources
|
|
||||||
=========
|
|
||||||
|
|
||||||
Frameworks
|
|
||||||
----------
|
|
||||||
|
|
||||||
* Please send a pull request!
|
|
||||||
|
|
||||||
Helper libraries
|
|
||||||
----------------
|
|
||||||
|
|
||||||
* [eventsource](https://github.com/jdavisp3/eventsource)
|
|
||||||
|
|
||||||
Articles
|
|
||||||
--------
|
|
||||||
|
|
||||||
* Please send a pull request!
|
|
|
@ -10,8 +10,9 @@ The REST handler is the recommended way to handle requests.
|
||||||
Initialization
|
Initialization
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Like Websocket, REST is a sub-protocol of HTTP. It therefore
|
First, the `init/3` callback is called. This callback is common
|
||||||
requires a protocol upgrade.
|
to all handlers. To use REST for the current request, this function
|
||||||
|
must return an `upgrade` tuple.
|
||||||
|
|
||||||
``` erlang
|
``` erlang
|
||||||
init({tcp, http}, Req, Opts) ->
|
init({tcp, http}, Req, Opts) ->
|
||||||
|
|
52
guide/toc.md
52
guide/toc.md
|
@ -24,6 +24,12 @@ HTTP
|
||||||
* [Sending a response](resp.md)
|
* [Sending a response](resp.md)
|
||||||
* [Using cookies](cookies.md)
|
* [Using cookies](cookies.md)
|
||||||
|
|
||||||
|
Multipart
|
||||||
|
---------
|
||||||
|
|
||||||
|
* [Introduction to multipart](multipart_intro.md)
|
||||||
|
* [Multipart requests](multipart_req.md)
|
||||||
|
|
||||||
Static files
|
Static files
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@ -36,48 +42,26 @@ REST
|
||||||
* [Handling REST requests](rest_handlers.md)
|
* [Handling REST requests](rest_handlers.md)
|
||||||
* [REST flowcharts](rest_flowcharts.md)
|
* [REST flowcharts](rest_flowcharts.md)
|
||||||
|
|
||||||
Multipart
|
Websocket
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* [Introduction to multipart](multipart_intro.md)
|
|
||||||
* [Multipart requests](multipart_req.md)
|
|
||||||
* Multipart responses
|
|
||||||
|
|
||||||
Server push technologies
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
* Push technologies
|
|
||||||
* [Using loop handlers for server push](loop_handlers.md)
|
|
||||||
* CORS
|
|
||||||
|
|
||||||
Using Websocket
|
|
||||||
---------------
|
|
||||||
|
|
||||||
* [The Websocket protocol](ws_protocol.md)
|
* [The Websocket protocol](ws_protocol.md)
|
||||||
* [Handling Websocket connections](ws_handlers.md)
|
* [Handling Websocket connections](ws_handlers.md)
|
||||||
|
|
||||||
Advanced HTTP
|
Server push
|
||||||
-------------
|
-----------
|
||||||
|
|
||||||
* Authentication
|
* [Loop handlers](loop_handlers.md)
|
||||||
* Sessions
|
|
||||||
|
|
||||||
Advanced Cowboy usage
|
Pluggable interface
|
||||||
---------------------
|
-------------------
|
||||||
|
|
||||||
* Optimization guide
|
|
||||||
* [Hooks](hooks.md)
|
|
||||||
* [Middlewares](middlewares.md)
|
* [Middlewares](middlewares.md)
|
||||||
* Access and error logs
|
* [Protocol upgrades](upgrade_protocol.md)
|
||||||
* Handling broken clients
|
* [Hooks](hooks.md)
|
||||||
* HTTP header names
|
|
||||||
* HTTP/1.1 streaming not chunked
|
|
||||||
|
|
||||||
Old guide misc
|
Internals
|
||||||
--------------
|
---------
|
||||||
|
|
||||||
This section will be removed as content is moved into other chapters.
|
* [Architecture](architecture.md)
|
||||||
|
* [Dealing with broken clients](broken_clients.md)
|
||||||
* [Handlers](handlers.md)
|
|
||||||
* [Internals](internals.md)
|
|
||||||
* [Resources](resources.md)
|
|
||||||
|
|
37
guide/upgrade_protocol.md
Normal file
37
guide/upgrade_protocol.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
Protocol upgrades
|
||||||
|
=================
|
||||||
|
|
||||||
|
Cowboy features many different handlers, each for different purposes.
|
||||||
|
All handlers have a common entry point: the `init/3` function.
|
||||||
|
|
||||||
|
The default handler type is the simple HTTP handler.
|
||||||
|
|
||||||
|
To switch to a different protocol, you must perform a protocol
|
||||||
|
upgrade. This is what is done for Websocket and REST and is
|
||||||
|
explained in details in the respective chapters.
|
||||||
|
|
||||||
|
You can also create your own protocol on top of Cowboy and use
|
||||||
|
the protocol upgrade mechanism to switch to it.
|
||||||
|
|
||||||
|
For example, if you create the `my_protocol` module implementing
|
||||||
|
the `cowboy_sub_protocol` behavior, then you can upgrade to it
|
||||||
|
by simply returning the module name from `init/3`.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
|
init(_, _, _Opts) ->
|
||||||
|
{upgrade, protocol, my_protocol}.
|
||||||
|
```
|
||||||
|
|
||||||
|
The `cowboy_sub_protocol` behavior only requires one callback,
|
||||||
|
`upgrade/4`. It receives the Req object, the middleware environment,
|
||||||
|
and the handler and options for this request. This is the same
|
||||||
|
module as the `init/3` function and the same options that were
|
||||||
|
passed to it.
|
||||||
|
|
||||||
|
``` erlang
|
||||||
|
upgrade(Req, Env, Handler, HandlerOpts) ->
|
||||||
|
%% ...
|
||||||
|
```
|
||||||
|
|
||||||
|
This callback is expected to behave like a middleware. Please
|
||||||
|
see the corresponding chapter for more information.
|
Loading…
Add table
Add a link
Reference in a new issue