aboutsummaryrefslogtreecommitdiffstats
path: root/doc/src/manual
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/manual')
-rw-r--r--doc/src/manual/cowboy.asciidoc1
-rw-r--r--doc/src/manual/cowboy.get_env.asciidoc78
-rw-r--r--doc/src/manual/cowboy.set_env.asciidoc1
-rw-r--r--doc/src/manual/cowboy_app.asciidoc1
-rw-r--r--doc/src/manual/cowboy_compress_h.asciidoc7
-rw-r--r--doc/src/manual/cowboy_decompress_h.asciidoc70
-rw-r--r--doc/src/manual/cowboy_http.asciidoc49
-rw-r--r--doc/src/manual/cowboy_http2.asciidoc41
-rw-r--r--doc/src/manual/cowboy_loop.asciidoc8
-rw-r--r--doc/src/manual/cowboy_metrics_h.asciidoc1
-rw-r--r--doc/src/manual/cowboy_req.asciidoc8
-rw-r--r--doc/src/manual/cowboy_req.cast.asciidoc16
-rw-r--r--doc/src/manual/cowboy_req.read_body.asciidoc10
-rw-r--r--doc/src/manual/cowboy_rest.asciidoc145
-rw-r--r--doc/src/manual/cowboy_static.asciidoc2
-rw-r--r--doc/src/manual/cowboy_stream.asciidoc17
-rw-r--r--doc/src/manual/cowboy_stream.data.asciidoc81
-rw-r--r--doc/src/manual/cowboy_stream.early_error.asciidoc73
-rw-r--r--doc/src/manual/cowboy_stream.info.asciidoc77
-rw-r--r--doc/src/manual/cowboy_stream.init.asciidoc80
-rw-r--r--doc/src/manual/cowboy_stream.terminate.asciidoc61
-rw-r--r--doc/src/manual/cowboy_stream_h.asciidoc56
-rw-r--r--doc/src/manual/cowboy_tracer_h.asciidoc1
-rw-r--r--doc/src/manual/cowboy_websocket.asciidoc4
24 files changed, 838 insertions, 50 deletions
diff --git a/doc/src/manual/cowboy.asciidoc b/doc/src/manual/cowboy.asciidoc
index c213df0..9298b6d 100644
--- a/doc/src/manual/cowboy.asciidoc
+++ b/doc/src/manual/cowboy.asciidoc
@@ -14,6 +14,7 @@ manipulating Ranch listeners.
* link:man:cowboy:start_clear(3)[cowboy:start_clear(3)] - Listen for connections using plain TCP
* link:man:cowboy:start_tls(3)[cowboy:start_tls(3)] - Listen for connections using TLS
* link:man:cowboy:stop_listener(3)[cowboy:stop_listener(3)] - Stop the given listener
+* link:man:cowboy:get_env(3)[cowboy:get_env(3)] - Retrieve a listener's environment value
* link:man:cowboy:set_env(3)[cowboy:set_env(3)] - Update a listener's environment value
== Types
diff --git a/doc/src/manual/cowboy.get_env.asciidoc b/doc/src/manual/cowboy.get_env.asciidoc
new file mode 100644
index 0000000..c2895b0
--- /dev/null
+++ b/doc/src/manual/cowboy.get_env.asciidoc
@@ -0,0 +1,78 @@
+= cowboy:get_env(3)
+
+== Name
+
+cowboy:get_env - Retrieve a listener's environment value
+
+== Description
+
+[source,erlang]
+----
+get_env(Name :: ranch:ref(),
+ Key :: atom())
+ -> any()
+
+get_env(Name :: ranch:ref(),
+ Key :: atom(),
+ Default :: any())
+ -> any()
+----
+
+Retrieve an environment value for a previously started
+listener.
+
+This function may crash when the key is missing from the
+environment and a default value is not provided.
+
+== Arguments
+
+Name::
+
+The name of the listener to access.
++
+The name of the listener is the first argument given to the
+link:man:cowboy:start_clear(3)[cowboy:start_clear(3)],
+link:man:cowboy:start_tls(3)[cowboy:start_tls(3)] or
+link:man:ranch:start_listener(3)[ranch:start_listener(3)] function.
+
+Key::
+
+The key in the environment map. Common keys include `dispatch`
+and `middlewares`.
+
+Default::
+
+The default value if the key is missing.
+
+== Return value
+
+The environment value is returned on success.
+
+If a default was provided and the key is missing, then the
+default value is returned.
+
+An `exit:badarg` exception is thrown when the listener does
+not exist.
+
+An `exit:{badkey, Key}` exception is thrown when the key
+requested is missing and no default was provided.
+
+== Changelog
+
+* *2.11*: Function introduced.
+
+== Examples
+
+.Retrieve a listener's routes
+[source,erlang]
+----
+Dispatch = cowboy:get_env(example, dispatch).
+----
+
+== See also
+
+link:man:cowboy(3)[cowboy(3)],
+link:man:cowboy:start_clear(3)[cowboy:start_clear(3)],
+link:man:cowboy:start_tls(3)[cowboy:start_tls(3)],
+link:man:cowboy:set_env(3)[cowboy:set_env(3)],
+link:man:ranch:get_protocol_options(3)[ranch:get_protocol_options(3)]
diff --git a/doc/src/manual/cowboy.set_env.asciidoc b/doc/src/manual/cowboy.set_env.asciidoc
index 30af485..fc0d1f7 100644
--- a/doc/src/manual/cowboy.set_env.asciidoc
+++ b/doc/src/manual/cowboy.set_env.asciidoc
@@ -76,4 +76,5 @@ cowboy:set_env(example, dispatch, Dispatch).
link:man:cowboy(3)[cowboy(3)],
link:man:cowboy:start_clear(3)[cowboy:start_clear(3)],
link:man:cowboy:start_tls(3)[cowboy:start_tls(3)],
+link:man:cowboy:get_env(3)[cowboy:get_env(3)],
link:man:ranch:set_protocol_options(3)[ranch:set_protocol_options(3)]
diff --git a/doc/src/manual/cowboy_app.asciidoc b/doc/src/manual/cowboy_app.asciidoc
index 8db84b1..fd833be 100644
--- a/doc/src/manual/cowboy_app.asciidoc
+++ b/doc/src/manual/cowboy_app.asciidoc
@@ -36,6 +36,7 @@ Stream handlers:
* link:man:cowboy_stream_h(3)[cowboy_stream_h(3)] - Default stream handler
* link:man:cowboy_compress_h(3)[cowboy_compress_h(3)] - Compress stream handler
+* link:man:cowboy_decompress_h(3)[cowboy_decompress_h(3)] - Decompress stream handler
* link:man:cowboy_metrics_h(3)[cowboy_metrics_h(3)] - Metrics stream handler
* link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)] - Tracer stream handler
diff --git a/doc/src/manual/cowboy_compress_h.asciidoc b/doc/src/manual/cowboy_compress_h.asciidoc
index 31a9162..6551567 100644
--- a/doc/src/manual/cowboy_compress_h.asciidoc
+++ b/doc/src/manual/cowboy_compress_h.asciidoc
@@ -9,7 +9,7 @@ cowboy_compress_h - Compress stream handler
The module `cowboy_compress_h` compresses response bodies
automatically when the client supports it. It will not
try to compress responses that already have a content
-encoding.
+encoding or that have an etag header defined.
Normal responses will only be compressed when their
size is lower than the configured threshold. Streamed
@@ -55,6 +55,10 @@ The compress stream handler does not produce any event.
== Changelog
+* *2.11*: Compression is now disabled when the etag
+ header is in the response headers.
+* *2.11*: The vary: accept-encoding header is now
+ always set when this handler is enabled.
* *2.6*: The options `compress_buffering` and
`compress_threshold` were added.
* *2.0*: Module introduced.
@@ -63,6 +67,7 @@ The compress stream handler does not produce any event.
link:man:cowboy(7)[cowboy(7)],
link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_decompress_h(3)[cowboy_decompress_h(3)],
link:man:cowboy_metrics_h(3)[cowboy_metrics_h(3)],
link:man:cowboy_stream_h(3)[cowboy_stream_h(3)],
link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)]
diff --git a/doc/src/manual/cowboy_decompress_h.asciidoc b/doc/src/manual/cowboy_decompress_h.asciidoc
new file mode 100644
index 0000000..8598ae4
--- /dev/null
+++ b/doc/src/manual/cowboy_decompress_h.asciidoc
@@ -0,0 +1,70 @@
+= cowboy_decompress_h(3)
+
+== Name
+
+cowboy_decompress_h - Decompress stream handler
+
+== Description
+
+The module `cowboy_decompress_h` decompresses request bodies
+automatically when the server supports it.
+
+The only compression algorithm currently supported is the
+gzip algorithm. Another limitation is that decompression
+is only attempted when gzip is the only content-encoding
+in the request.
+
+This stream handler always adds a field to the Req object
+with the name `content_decoded` which is treated as a
+list of decoded content-encoding values. Currently this
+list may only contain the `<<"gzip">>` binary if content
+was decoded; or be empty otherwise.
+
+== Options
+
+[source,erlang]
+----
+opts() :: #{
+ decompress_enabled => boolean(),
+ decompress_ratio_limit => non_neg_integer()
+}
+----
+
+Configuration for the decompress stream handler.
+
+The default value is given next to the option name:
+
+decompress_ratio_limit (20)::
+The max ratio of the compressed and decompressed body
+before it is rejected with a `413 Payload Too Large`
+error response.
++
+This option can be updated at any time using the
+`set_options` stream handler command.
+
+decompress_enabled (true)::
+
+Whether the handler is enabled by default.
++
+This option can be updated using the `set_options`
+stream handler command. This allows disabling
+decompression for the current stream. Attempts
+to enable or disable decompression after starting
+to read the body will be ignored.
+
+== Events
+
+The decompress stream handler does not produce any event.
+
+== Changelog
+
+* *2.11*: Module introduced.
+
+== See also
+
+link:man:cowboy(7)[cowboy(7)],
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_compress_h(3)[cowboy_compress_h(3)],
+link:man:cowboy_metrics_h(3)[cowboy_metrics_h(3)],
+link:man:cowboy_stream_h(3)[cowboy_stream_h(3)],
+link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)]
diff --git a/doc/src/manual/cowboy_http.asciidoc b/doc/src/manual/cowboy_http.asciidoc
index 33d2888..58f0435 100644
--- a/doc/src/manual/cowboy_http.asciidoc
+++ b/doc/src/manual/cowboy_http.asciidoc
@@ -17,27 +17,28 @@ as a Ranch protocol.
[source,erlang]
----
opts() :: #{
- active_n => pos_integer(),
- chunked => boolean(),
- connection_type => worker | supervisor,
- http10_keepalive => boolean(),
- idle_timeout => timeout(),
- inactivity_timeout => timeout(),
- initial_stream_flow_size => non_neg_integer(),
- linger_timeout => timeout(),
- logger => module(),
- max_empty_lines => non_neg_integer(),
- max_header_name_length => non_neg_integer(),
- max_header_value_length => non_neg_integer(),
- max_headers => non_neg_integer(),
- max_keepalive => non_neg_integer(),
- max_method_length => non_neg_integer(),
- max_request_line_length => non_neg_integer(),
- max_skip_body_length => non_neg_integer(),
- proxy_header => boolean(),
- request_timeout => timeout(),
- sendfile => boolean(),
- stream_handlers => [module()]
+ active_n => pos_integer(),
+ chunked => boolean(),
+ connection_type => worker | supervisor,
+ http10_keepalive => boolean(),
+ idle_timeout => timeout(),
+ inactivity_timeout => timeout(),
+ initial_stream_flow_size => non_neg_integer(),
+ linger_timeout => timeout(),
+ logger => module(),
+ max_empty_lines => non_neg_integer(),
+ max_header_name_length => non_neg_integer(),
+ max_header_value_length => non_neg_integer(),
+ max_headers => non_neg_integer(),
+ max_keepalive => non_neg_integer(),
+ max_method_length => non_neg_integer(),
+ max_request_line_length => non_neg_integer(),
+ max_skip_body_length => non_neg_integer(),
+ proxy_header => boolean(),
+ request_timeout => timeout(),
+ reset_idle_timeout_on_send => boolean(),
+ sendfile => boolean(),
+ stream_handlers => [module()]
}
----
@@ -148,6 +149,11 @@ request_timeout (5000)::
Time in ms with no requests before Cowboy closes the connection.
+reset_idle_timeout_on_send (false)::
+
+Whether the `idle_timeout` gets reset when sending data
+to the socket.
+
sendfile (true)::
Whether the sendfile syscall may be used. It can be useful to disable
@@ -160,6 +166,7 @@ Ordered list of stream handlers that will handle all stream events.
== Changelog
+* *2.11*: The `reset_idle_timeout_on_send` option was added.
* *2.8*: The `active_n` option was added.
* *2.7*: The `initial_stream_flow_size` and `logger` options were added.
* *2.6*: The `chunked`, `http10_keepalive`, `proxy_header` and `sendfile` options were added.
diff --git a/doc/src/manual/cowboy_http2.asciidoc b/doc/src/manual/cowboy_http2.asciidoc
index 9be1de8..1d2619c 100644
--- a/doc/src/manual/cowboy_http2.asciidoc
+++ b/doc/src/manual/cowboy_http2.asciidoc
@@ -35,14 +35,17 @@ opts() :: #{
max_connection_window_size => 0..16#7fffffff,
max_decode_table_size => non_neg_integer(),
max_encode_table_size => non_neg_integer(),
+ max_fragmented_header_block_size => 16384..16#7fffffff,
max_frame_size_received => 16384..16777215,
max_frame_size_sent => 16384..16777215 | infinity,
max_received_frame_rate => {pos_integer(), timeout()},
max_reset_stream_rate => {pos_integer(), timeout()},
+ max_cancel_stream_rate => {pos_integer(), timeout()},
max_stream_buffer_size => non_neg_integer(),
max_stream_window_size => 0..16#7fffffff,
preface_timeout => timeout(),
proxy_header => boolean(),
+ reset_idle_timeout_on_send => boolean(),
sendfile => boolean(),
settings_timeout => timeout(),
stream_handlers => [module()],
@@ -92,7 +95,10 @@ enable_connect_protocol (false)::
Whether to enable the extended CONNECT method to allow
protocols like Websocket to be used over an HTTP/2 stream.
-This option is experimental and disabled by default.
++
+For backward compatibility reasons, this option is disabled
+by default. It must be enabled to use Websocket over HTTP/2.
+It will be enabled by default in a future release.
goaway_initial_timeout (1000)::
@@ -167,11 +173,25 @@ Maximum header table size in bytes used by the encoder. The server will
compare this value to what the client advertises and choose the smallest
one as the encoder's header table size.
+max_fragmented_header_block_size (32768)::
+
+Maximum header block size when headers are split over multiple HEADERS
+and CONTINUATION frames. Clients that attempt to send header blocks
+larger than this value will receive an ENHANCE_YOUR_CALM connection
+error. Note that this value is not advertised and should be large
+enough for legitimate requests.
+
max_frame_size_received (16384)::
Maximum size in bytes of the frames received by the server. This value is
advertised to the remote endpoint which can then decide to use
any value lower or equal for its frame sizes.
++
+It is highly recommended to increase this value for performance reasons.
+In a future Cowboy version the default will be increased to 1MB (1048576).
+Too low values may result in very large file uploads failing because
+Cowboy will detect the large number of frames as flood and close the
+connection.
max_frame_size_sent (infinity)::
@@ -198,6 +218,14 @@ the number of streams that can be reset over a certain time period.
The rate is expressed as a tuple `{NumResets, TimeMs}`. This is
similar to a supervisor restart intensity/period.
+max_cancel_stream_rate ({500, 10000})::
+
+Maximum cancel stream rate per connection. This can be used to
+protect against misbehaving or malicious peers, by limiting the
+number of streams that the peer can reset over a certain time period.
+The rate is expressed as a tuple `{NumCancels, TimeMs}`. This is
+similar to a supervisor restart intensity/period.
+
max_stream_buffer_size (8000000)::
Maximum stream buffer size in bytes. This is a soft limit used
@@ -220,6 +248,11 @@ Whether incoming connections have a PROXY protocol header. The
proxy information will be passed forward via the `proxy_header`
key of the Req object.
+reset_idle_timeout_on_send (false)::
+
+Whether the `idle_timeout` gets reset when sending data
+to the socket.
+
sendfile (true)::
Whether the sendfile syscall may be used. It can be useful to disable
@@ -256,6 +289,10 @@ too many `WINDOW_UPDATE` frames.
== Changelog
+* *2.11*: Websocket over HTTP/2 is now considered stable.
+* *2.11*: The `reset_idle_timeout_on_send` option was added.
+* *2.11*: Add the option `max_cancel_stream_rate` to protect
+ against another flood scenario.
* *2.9*: The `goaway_initial_timeout` and `goaway_complete_timeout`
options were added.
* *2.8*: The `active_n` option was added.
@@ -283,7 +320,7 @@ too many `WINDOW_UPDATE` frames.
`max_frame_size_received`, `max_frame_size_sent`
and `settings_timeout` to configure HTTP/2 SETTINGS
and related behavior.
-* *2.4*: Add the experimental option `enable_connect_protocol`.
+* *2.4*: Add the option `enable_connect_protocol`.
* *2.0*: Protocol introduced.
== See also
diff --git a/doc/src/manual/cowboy_loop.asciidoc b/doc/src/manual/cowboy_loop.asciidoc
index 000149d..8c9a816 100644
--- a/doc/src/manual/cowboy_loop.asciidoc
+++ b/doc/src/manual/cowboy_loop.asciidoc
@@ -28,11 +28,11 @@ Loop handlers implement the following interface:
----
init(Req, State)
-> {cowboy_loop, Req, State}
- | {cowboy_loop, Req, State, hibernate}
+ | {cowboy_loop, Req, State, hibernate | timeout()}
info(Info, Req, State)
-> {ok, Req, State}
- | {ok, Req, State, hibernate}
+ | {ok, Req, State, hibernate | timeout()}
| {stop, Req, State}
terminate(Reason, Req, State) -> ok %% optional
@@ -69,7 +69,9 @@ stop::
== Changelog
-* *2.0*: Loop handlers no longer need to handle overflow/timeouts.
+* *2.11*: A timeout may be returned instead of `hibernate`.
+ It functions the same way as the `gen_server` timeout.
+* *2.0*: Loop handlers no longer need to handle socket events.
* *1.0*: Behavior introduced.
== See also
diff --git a/doc/src/manual/cowboy_metrics_h.asciidoc b/doc/src/manual/cowboy_metrics_h.asciidoc
index c871d57..801bdbb 100644
--- a/doc/src/manual/cowboy_metrics_h.asciidoc
+++ b/doc/src/manual/cowboy_metrics_h.asciidoc
@@ -160,5 +160,6 @@ The metrics stream handler does not produce any event.
link:man:cowboy(7)[cowboy(7)],
link:man:cowboy_stream(3)[cowboy_stream(3)],
link:man:cowboy_compress_h(3)[cowboy_compress_h(3)],
+link:man:cowboy_decompress_h(3)[cowboy_decompress_h(3)],
link:man:cowboy_stream_h(3)[cowboy_stream_h(3)],
link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)]
diff --git a/doc/src/manual/cowboy_req.asciidoc b/doc/src/manual/cowboy_req.asciidoc
index 0a1ca1b..0367836 100644
--- a/doc/src/manual/cowboy_req.asciidoc
+++ b/doc/src/manual/cowboy_req.asciidoc
@@ -120,8 +120,8 @@ request's URI.
[source,erlang]
----
read_body_opts() :: #{
- length => non_neg_integer(),
- period => non_neg_integer(),
+ length => non_neg_integer() | auto,
+ period => non_neg_integer() | infinity,
timeout => timeout()
}
----
@@ -130,6 +130,10 @@ Body reading options.
The defaults are function-specific.
+Auto mode can be enabled by setting `length` to `auto`
+and `period` to `infinity`. The period cannot be set
+to `infinity` when auto mode isn't used.
+
=== req()
[source,erlang]
diff --git a/doc/src/manual/cowboy_req.cast.asciidoc b/doc/src/manual/cowboy_req.cast.asciidoc
index d6e018f..b12157f 100644
--- a/doc/src/manual/cowboy_req.cast.asciidoc
+++ b/doc/src/manual/cowboy_req.cast.asciidoc
@@ -36,6 +36,22 @@ The atom `ok` is always returned. It can be safely ignored.
== Examples
+.Read the body using auto mode
+[source,erlang]
+----
+read_body_auto_async(Req) ->
+ read_body_auto_async(Req, make_ref(), <<>>).
+
+read_body_auto_async(Req, Ref, Acc) ->
+ cowboy_req:cast({read_body, self(), Ref, auto, infinity}, Req),
+ receive
+ {request_body, Ref, nofin, Data} ->
+ read_body_auto_async(Req, Ref, <<Acc/binary, Data/binary>>);
+ {request_body, Ref, fin, _BodyLen, Data} ->
+ {ok, <<Acc/binary, Data/binary>>, Req}
+ end.
+----
+
.Increase the HTTP/1.1 idle timeout
[source,erlang]
----
diff --git a/doc/src/manual/cowboy_req.read_body.asciidoc b/doc/src/manual/cowboy_req.read_body.asciidoc
index 2b87405..7da76ef 100644
--- a/doc/src/manual/cowboy_req.read_body.asciidoc
+++ b/doc/src/manual/cowboy_req.read_body.asciidoc
@@ -68,6 +68,13 @@ The `timeout` option is a safeguard in case the connection
process becomes unresponsive. The function will crash if no
message was received in that interval. The timeout should be
larger than the period. It defaults to the period + 1 second.
++
+Auto mode can be enabled by setting the `length` to `auto` and
+the `period` to `infinity`. When auto mode is used, Cowboy will
+send data to the handler as soon as it receives it, regardless
+of its size. It will wait indefinitely until data is available.
+Auto mode's main purpose is asynchronous body reading using
+link:man:cowboy_req:cast(3)[cowboy_req:cast(3)].
== Return value
@@ -86,6 +93,9 @@ body has been read.
== Changelog
+* *2.11*: The `length` option now accepts `auto` and the
+ period now accepts `infinity`. This adds support for
+ reading the body in auto mode.
* *2.0*: Function introduced. Replaces `body/1,2`.
== Examples
diff --git a/doc/src/manual/cowboy_rest.asciidoc b/doc/src/manual/cowboy_rest.asciidoc
index 0bb6d47..fcef799 100644
--- a/doc/src/manual/cowboy_rest.asciidoc
+++ b/doc/src/manual/cowboy_rest.asciidoc
@@ -379,7 +379,7 @@ and that the request shouldn't be repeated.
----
generate_etag(Req, State) -> {Result, Req, State}
-Result :: binary() | {weak | strong, binary()}
+Result :: binary() | {weak | strong, binary()} | undefined
Default - no etag value
----
@@ -389,6 +389,10 @@ When a binary is returned, the value is automatically
parsed to a tuple. The binary must be in the same
format as the etag header, including quotes.
+It is possible to conditionally generate an etag.
+When no etag can be generated, `undefined` should
+be returned.
+
=== is_authorized
[source,erlang]
@@ -601,17 +605,139 @@ The response body can be provided either as the actual data
to be sent or a tuple indicating which file to send.
This function is called for both GET and HEAD requests. For
-the latter the body is not sent, however.
+the latter the body is not sent: it is only used to calculate
+the content length.
// @todo Perhaps we can optimize HEAD requests and just
// allow calculating the length instead of returning the
// whole thing.
-Note that there used to be a way to stream the response body.
-It was temporarily removed and will be added back in a later
-release.
+It is possible to stream the response body either by manually
+sending the response and returning a `stop` value; or by
+switching to a different handler (for example a loop handler)
+and manually sending the response. All headers already set
+by Cowboy will also be included in the response.
+
+== RangeCallback
+
+[source,erlang]
+----
+RangeCallback(Req, State) -> {Result, Req, State}
+
+Result :: [{Range, Body}]
+Range :: {From, To, Total} | binary()
+From :: non_neg_integer()
+To :: non_neg_integer()
+Total :: non_neg_integer() | '*'
+Body :: cowboy_req:resp_body()
+Default - crash
+----
+
+Return a list of ranges for the response body.
+
+The range selected can be found in the key `range`
+in the Req object, as indicated in `range_satisfiable`.
+
+Instead of returning the full response body as would
+be done in the `ProvideCallback`, a list of ranges
+must be returned. There can be one or more range.
+When one range is returned, a normal ranged response
+is sent. When multiple ranges are returned, Cowboy
+will automatically send a multipart/byteranges
+response.
+
+When the total is not known the atom `'*'` can be
+returned.
+
+== ranges_provided
+
+[source,erlang]
+----
+ranges_provided(Req, State) -> {Result, Req, State}
+
+Result :: [Range | Auto]
+Range :: {
+ binary(), %% lowercase; case insensitive
+ RangeCallback :: atom()
+}
+Auto :: {<<"bytes">>, auto}
+Default - skip this step
+----
+
+Return the list of range units the resource provides.
+
+During content negotiation Cowboy will build an accept-ranges
+response header with the list of ranges provided. Cowboy
+does not choose a range at this time; ranges are choosen
+when it comes time to call the `ProvideCallback`.
+
+By default ranged requests will be handled the same as normal
+requests: the `ProvideCallback` will be called and the full
+response body will be sent.
+
+It is possible to let Cowboy handle ranged responses
+automatically when the range unit is bytes and the
+atom returned is `auto` (instead of a callback name).
+In that case Cowboy will call the `ProvideCallback`
+and split the response automatically, including by
+producing a multipart/byteranges response if necessary.
+
+== range_satisfiable
+
+[source,erlang]
+----
+range_satisfiable(Req, State) -> {Result, Req, State}
+
+Result :: boolean() | {false, non_neg_integer() | iodata()}
+Default :: true
+----
+
+Whether the range request is satisfiable.
+
+When the time comes to send the response body, and when
+ranges have been provided via the `ranges_provided`
+callback, Cowboy will process the if-range and the
+range request headers and ensure it is satisfiable.
+
+This callback allows making resource-specific checks
+before sending the ranged response. The default is
+to accept sending a ranged response.
+
+Cowboy adds the requested `range` to the Req object
+just before calling this callback:
+
+[source,erlang]
+----
+req() :: #{
+ range => {
+ binary(), %% lowercase; case insensitive
+ Range
+ }
+}
+
+Range :: ByteRange | binary()
+
+ByteRange :: [{FirstByte, LastByte | infinity} | SuffixLen]
+FirstByte :: non_neg_integer()
+LastByte :: non_neg_integer()
+SuffixLen :: neg_integer()
+----
+
+Only byte ranges are parsed. Other ranges are provided
+as binary. Byte ranges may either be requested from first
+to last bytes (inclusive); from first bytes to the end
+(`infinity` is used to represent the last byte); or
+the last bytes of the representation via a negative
+integer (so -500 means the last 500 bytes).
-// @todo Add a way to switch to loop handler for streaming the body.
+Returning `false` will result in a 416 Range Not Satisfiable
+response being sent. The content-range header will be
+set automatically in the response if a tuple is
+returned. The integer value represents the total
+size (in the choosen unit) of the resource. An
+iodata value may also be returned and will be
+used as-is to build the content range header,
+prepended with the unit choosen.
=== rate_limited
@@ -621,7 +747,7 @@ rate_limited(Req, State) -> {Result, Req, State}
Result :: false | {true, RetryAfter}
RetryAfter :: non_neg_integer() | calendar:datetime()
-Default - false
+Default :: false
----
Return whether the user is rate limited.
@@ -730,6 +856,11 @@ listed here, like the authorization header.
== Changelog
+* *2.11*: The `ranges_provided`, `range_satisfiable` and
+ the `RangeCallback` callbacks have been added.
+* *2.11*: The `generate_etag` callback can now return
+ `undefined` to conditionally avoid generating
+ an etag.
* *2.9*: An `AcceptCallback` can now return `{created, URI}` or
`{see_other, URI}`. The return value `{true, URI}`
is deprecated.
diff --git a/doc/src/manual/cowboy_static.asciidoc b/doc/src/manual/cowboy_static.asciidoc
index 0e131dd..dde3401 100644
--- a/doc/src/manual/cowboy_static.asciidoc
+++ b/doc/src/manual/cowboy_static.asciidoc
@@ -129,6 +129,8 @@ when it fails to detect a file's MIME type.
== Changelog
+* *2.11*: Support for range requests was added in 2.6 and
+ is now considered stable.
* *2.6*: The `charset` extra option was added.
* *1.0*: Handler introduced.
diff --git a/doc/src/manual/cowboy_stream.asciidoc b/doc/src/manual/cowboy_stream.asciidoc
index 65bd06e..25a9cf9 100644
--- a/doc/src/manual/cowboy_stream.asciidoc
+++ b/doc/src/manual/cowboy_stream.asciidoc
@@ -52,11 +52,11 @@ HTTP/1.1 will initialize a stream only when the request-line
and all headers have been received. When errors occur before
that point Cowboy will call the callback `early_error/5`
with a partial request, the error reason and the response
-Cowboy intends to send. All other events go throuh the
+Cowboy intends to send. All other events go through the
stream handler using the normal callbacks.
HTTP/2 will initialize the stream when the `HEADERS` block has
-been fully received and decoded. Any protocol error occuring
+been fully received and decoded. Any protocol error occurring
before that will not result in a response being sent and
will therefore not go through the stream handler. In addition
Cowboy may terminate streams without sending an HTTP response
@@ -84,6 +84,13 @@ the `early_error/5` callback must return a response command.
// @todo The logger option and the {log, Level, Format, Args}
// options need to be documented and tested.
+The order in which the commands are given matters. For example,
+when sending a response and at the same time creating a new child
+process, the first command should be the `spawn` and the second the
+`response`. The reason for that is that the sending of the response
+may result in a socket error which leads to the termination of
+the connection before the rest of the commands are executed.
+
The following commands are defined:
[[inform_command]]
@@ -236,6 +243,8 @@ will end successfully as far as the client is concerned.
To indicate that an error occurred, either use `error_response`
before stopping, or use `internal_error`.
+No other command can be executed after the `stop` command.
+
=== internal_error
Stop the stream with an error.
@@ -278,7 +287,7 @@ This can also be used to override stream handler
options. For example this is supported by
link:man:cowboy_compress_h(3)[cowboy_compress_h(3)].
-Not all options can be overriden. Please consult the
+Not all options can be overridden. Please consult the
relevant option's documentation for details.
== Predefined events
@@ -335,7 +344,7 @@ fin() :: fin | nofin
----
Used in commands and events to indicate that this is
-the end of the stream.
+the end of a direction of a stream.
=== partial_req()
diff --git a/doc/src/manual/cowboy_stream.data.asciidoc b/doc/src/manual/cowboy_stream.data.asciidoc
new file mode 100644
index 0000000..a0328f6
--- /dev/null
+++ b/doc/src/manual/cowboy_stream.data.asciidoc
@@ -0,0 +1,81 @@
+= cowboy_stream:data(3)
+
+== Name
+
+cowboy_stream:data - Handle data for a stream
+
+== Description
+
+[source,erlang]
+----
+data(StreamID, IsFin, Data, State) -> {Commands, State}
+
+StreamID :: cowboy_stream:stream_id()
+IsFin :: cowboy_stream:fin()
+Data :: binary()
+Commands :: cowboy_stream:commands()
+State - opaque
+----
+
+Handle data for a stream.
+
+This function should be called by all stream handlers. It will
+propagate data to the next configured stream handler. Handlers
+do not have to propagate data that has been fully handled.
+
+== Arguments
+
+StreamID::
+
+The stream ID.
+
+IsFin::
+
+Whether this is the end of the request body.
+
+Data::
+
+The data received.
+
+Commands::
+
+The commands to be executed.
+
+State::
+
+The state for the next stream handler.
+
+== Return value
+
+A list of commands and an opaque state is returned.
+
+The list of commands returned should be included in the
+commands returned from the current stream handler. It
+can be modified if necessary.
+
+The state should be stored in the current stream
+handler's state and passed to `cowboy_stream` when
+necessary. The state should be treated as opaque.
+
+== Changelog
+
+* *2.0*: Function introduced.
+
+== Examples
+
+.Propagate data to the next stream handler
+[source,erlang]
+----
+data(StreamID, IsFin, Data, State=#state{next=Next0}) ->
+ MyCommands = my_commands(),
+ {Commands, Next} = cowboy_stream:data(StreamID, IsFin, Data, Next0),
+ {MyCommands ++ Commands, #state{next=Next}}.
+----
+
+== See also
+
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_stream:init(3)[cowboy_stream:init(3)],
+link:man:cowboy_stream:info(3)[cowboy_stream:info(3)],
+link:man:cowboy_stream:terminate(3)[cowboy_stream:terminate(3)],
+link:man:cowboy_stream:early_error(3)[cowboy_stream:early_error(3)]
diff --git a/doc/src/manual/cowboy_stream.early_error.asciidoc b/doc/src/manual/cowboy_stream.early_error.asciidoc
new file mode 100644
index 0000000..ad1d6bf
--- /dev/null
+++ b/doc/src/manual/cowboy_stream.early_error.asciidoc
@@ -0,0 +1,73 @@
+= cowboy_stream:early_error(3)
+
+== Name
+
+cowboy_stream:early_error - Handle an early error for a stream
+
+== Description
+
+[source,erlang]
+----
+early_error(StreamID, Reason, PartialReq, Resp, Opts) -> Resp
+
+StreamID :: cowboy_stream:stream_id()
+Reason :: cowboy_stream:reason()
+PartialReq :: cowboy_stream:partial_req()
+Resp :: cowboy_stream:resp_command()
+Opts :: cowboy:opts()
+----
+
+Handle an early error for a stream.
+
+This function should be called by all stream handlers. It will
+propagate the early error to the next configured stream handler.
+
+== Arguments
+
+StreamID::
+
+The stream ID.
+
+Reason::
+
+Reason for termination.
+
+PartialReq::
+
+The request data that has been received so far.
+
+Resp::
+
+The response that will be sent as a result of the early error.
++
+It may be modified by the stream handler before or after
+being propagated to the next handler.
+
+Opts::
+
+The protocol options.
+
+== Return value
+
+The response to be sent as a result of the early error.
+
+== Changelog
+
+* *2.0*: Function introduced.
+
+== Examples
+
+.Propagate the early error to the next stream handler
+[source,erlang]
+----
+early_error(StreamID, Reason, PartialReq, Resp, Opts) ->
+ cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp, Opts).
+----
+
+== See also
+
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_stream:init(3)[cowboy_stream:init(3)],
+link:man:cowboy_stream:data(3)[cowboy_stream:data(3)],
+link:man:cowboy_stream:info(3)[cowboy_stream:info(3)],
+link:man:cowboy_stream:terminate(3)[cowboy_stream:terminate(3)]
diff --git a/doc/src/manual/cowboy_stream.info.asciidoc b/doc/src/manual/cowboy_stream.info.asciidoc
new file mode 100644
index 0000000..32cbd85
--- /dev/null
+++ b/doc/src/manual/cowboy_stream.info.asciidoc
@@ -0,0 +1,77 @@
+= cowboy_stream:info(3)
+
+== Name
+
+cowboy_stream:info - Handle a message for a stream
+
+== Description
+
+[source,erlang]
+----
+info(StreamID, Info, State) -> {Commands, State}
+
+StreamID :: cowboy_stream:stream_id()
+Info :: any()
+Commands :: cowboy_stream:commands()
+State - opaque
+----
+
+Handle a message for a stream.
+
+This function should be called by all stream handlers. It will
+propagate the event to the next configured stream handler.
+Handlers do not have to propagate events that have been
+fully handled.
+
+== Arguments
+
+StreamID::
+
+The stream ID.
+
+Info::
+
+The event received.
+
+Commands::
+
+The commands to be executed.
+
+State::
+
+The state for the next stream handler.
+
+== Return value
+
+A list of commands and an opaque state is returned.
+
+The list of commands returned should be included in the
+commands returned from the current stream handler. It
+can be modified if necessary.
+
+The state should be stored in the current stream
+handler's state and passed to `cowboy_stream` when
+necessary. The state should be treated as opaque.
+
+== Changelog
+
+* *2.0*: Function introduced.
+
+== Examples
+
+.Propagate an event to the next stream handler
+[source,erlang]
+----
+info(StreamID, Info, State=#state{next=Next0}) ->
+ MyCommands = my_commands(),
+ {Commands, Next} = cowboy_stream:info(StreamID, Info, Next0),
+ {MyCommands ++ Commands, #state{next=Next}}.
+----
+
+== See also
+
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_stream:init(3)[cowboy_stream:init(3)],
+link:man:cowboy_stream:data(3)[cowboy_stream:data(3)],
+link:man:cowboy_stream:terminate(3)[cowboy_stream:terminate(3)],
+link:man:cowboy_stream:early_error(3)[cowboy_stream:early_error(3)]
diff --git a/doc/src/manual/cowboy_stream.init.asciidoc b/doc/src/manual/cowboy_stream.init.asciidoc
new file mode 100644
index 0000000..addf9bc
--- /dev/null
+++ b/doc/src/manual/cowboy_stream.init.asciidoc
@@ -0,0 +1,80 @@
+= cowboy_stream:init(3)
+
+== Name
+
+cowboy_stream:init - Initialize a stream
+
+== Description
+
+[source,erlang]
+----
+init(StreamID, Req, Opts) -> {Commands, State}
+
+StreamID :: cowboy_stream:stream_id()
+Req :: cowboy_req:req()
+Opts :: cowboy:opts()
+Commands :: cowboy_stream:commands()
+State - opaque
+----
+
+Initialize a stream.
+
+This function must be called by all stream handlers. It will
+initialize the next configured stream handler.
+
+== Arguments
+
+StreamID::
+
+The stream ID.
+
+Req::
+
+The Req object.
+
+Opts::
+
+The protocol options.
+
+Commands::
+
+The commands to be executed.
+
+State::
+
+The state for the next stream handler.
+
+== Return value
+
+A list of commands and an opaque state is returned.
+
+The list of commands returned should be included in the
+commands returned from the current stream handler. It
+can be modified if necessary.
+
+The state should be stored in the current stream
+handler's state and passed to `cowboy_stream` when
+necessary. The state should be treated as opaque.
+
+== Changelog
+
+* *2.0*: Function introduced.
+
+== Examples
+
+.Initialize the next stream handler
+[source,erlang]
+----
+init(StreamID, Req, Opts) ->
+ MyCommands = my_commands(),
+ {Commands, Next} = cowboy_stream:init(StreamID, Req, Opts),
+ {MyCommands ++ Commands, #state{next=Next}}.
+----
+
+== See also
+
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_stream:data(3)[cowboy_stream:data(3)],
+link:man:cowboy_stream:info(3)[cowboy_stream:info(3)],
+link:man:cowboy_stream:terminate(3)[cowboy_stream:terminate(3)],
+link:man:cowboy_stream:early_error(3)[cowboy_stream:early_error(3)]
diff --git a/doc/src/manual/cowboy_stream.terminate.asciidoc b/doc/src/manual/cowboy_stream.terminate.asciidoc
new file mode 100644
index 0000000..8393801
--- /dev/null
+++ b/doc/src/manual/cowboy_stream.terminate.asciidoc
@@ -0,0 +1,61 @@
+= cowboy_stream:terminate(3)
+
+== Name
+
+cowboy_stream:terminate - Terminate a stream
+
+== Description
+
+[source,erlang]
+----
+terminate(StreamID, Reason, State) -> ok
+
+StreamID :: cowboy_stream:stream_id()
+Reason :: cowboy_stream:reason()
+State - opaque
+----
+
+Terminate a stream.
+
+This function must be called by all stream handlers. It will
+terminate the next configured stream handler.
+
+== Arguments
+
+StreamID::
+
+The stream ID.
+
+Reason::
+
+Reason for termination.
+
+State::
+
+The state for the next stream handler.
+
+== Return value
+
+The atom `ok` is always returned. It can be safely ignored.
+
+== Changelog
+
+* *2.0*: Function introduced.
+
+== Examples
+
+.Terminate the next stream handler
+[source,erlang]
+----
+terminate(StreamID, Reason, State=#state{next=Next0}) ->
+ my_termination(State),
+ cowboy_stream:terminate(StreamID, Reason, Next0).
+----
+
+== See also
+
+link:man:cowboy_stream(3)[cowboy_stream(3)],
+link:man:cowboy_stream:init(3)[cowboy_stream:init(3)],
+link:man:cowboy_stream:data(3)[cowboy_stream:data(3)],
+link:man:cowboy_stream:info(3)[cowboy_stream:info(3)],
+link:man:cowboy_stream:early_error(3)[cowboy_stream:early_error(3)]
diff --git a/doc/src/manual/cowboy_stream_h.asciidoc b/doc/src/manual/cowboy_stream_h.asciidoc
index c25aa3d..7e0af89 100644
--- a/doc/src/manual/cowboy_stream_h.asciidoc
+++ b/doc/src/manual/cowboy_stream_h.asciidoc
@@ -45,8 +45,49 @@ The default stream handler spawns the request process
and receives its exit signal when it terminates. It
will stop the stream once its receives it.
-// @todo It also implements the read_body mechanism.
-// Note that cowboy_stream_h sends the 100-continue automatically.
+Because this stream handler converts events from the
+request process into commands, other stream handlers
+may not work properly if they are executed after the
+default stream handler. Always be mindful of in which
+order stream handlers will get executed.
+
+=== Request body
+
+The default stream handler implements the `read_body`
+mechanism. In addition to reading the body, the handler
+will automatically handle the `expect: 100-continue`
+header and send a 100 Continue response.
+
+Normally one would use
+link:man:cowboy_req:read_body(3)[cowboy_req:read_body(3)]
+to read the request body. The default stream handler
+will buffer data until the amount gets larger than the
+requested length before sending it. Alternatively, it
+will send whatever data it has when the period timeout
+triggers. Depending on the protocol, the flow control
+window is updated to allow receiving data for the
+requested length.
+
+The default stream handler also comes with an automatic
+mode for reading the request body. This can be used by
+sending the event message `{read_body, Pid, Ref, auto, infinity}`
+using link:man:cowboy_req:cast(3)[cowboy_req:cast(3)].
+The default stream handler will then send data as soon
+as some becomes available using one of these two
+messages depending on whether body reading was completed:
+
+* `{request_body, Ref, nofin, Data}`
+* `{request_body, Ref, fin, BodyLen, Data}`
+
+Depending on the protocol, Cowboy will update the flow
+control window using the size of the data that was read.
+
+Auto mode automatically gets disabled after data has
+been sent to the handler. Therefore in order to continue
+reading data a `read_body` event message must be sent
+after each `request_body` message.
+
+=== Response
In addition it returns a command for any event message
looking like one of the following commands: `inform`,
@@ -54,14 +95,9 @@ looking like one of the following commands: `inform`,
`switch_protocol`. This is what allows the request
process to send a response.
-// @todo Add set_options, which updates options dynamically.
-
-Because this stream handler converts events from the
-request process into commands, other stream handlers
-may not work properly if they are executed
-
== Changelog
+* *2.11*: Introduce body reading using auto mode.
* *2.0*: Module introduced.
== See also
@@ -69,5 +105,7 @@ may not work properly if they are executed
link:man:cowboy(7)[cowboy(7)],
link:man:cowboy_stream(3)[cowboy_stream(3)],
link:man:cowboy_compress_h(3)[cowboy_compress_h(3)],
+link:man:cowboy_decompress_h(3)[cowboy_decompress_h(3)],
link:man:cowboy_metrics_h(3)[cowboy_metrics_h(3)],
-link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)]
+link:man:cowboy_tracer_h(3)[cowboy_tracer_h(3)],
+link:man:cowboy_req:cast(3)[cowboy_req:cast(3)]
diff --git a/doc/src/manual/cowboy_tracer_h.asciidoc b/doc/src/manual/cowboy_tracer_h.asciidoc
index e3592e4..4f4e9bc 100644
--- a/doc/src/manual/cowboy_tracer_h.asciidoc
+++ b/doc/src/manual/cowboy_tracer_h.asciidoc
@@ -84,5 +84,6 @@ The tracer stream handler does not produce any event.
link:man:cowboy(7)[cowboy(7)],
link:man:cowboy_stream(3)[cowboy_stream(3)],
link:man:cowboy_compress_h(3)[cowboy_compress_h(3)],
+link:man:cowboy_decompress_h(3)[cowboy_decompress_h(3)],
link:man:cowboy_metrics_h(3)[cowboy_metrics_h(3)],
link:man:cowboy_stream_h(3)[cowboy_stream_h(3)]
diff --git a/doc/src/manual/cowboy_websocket.asciidoc b/doc/src/manual/cowboy_websocket.asciidoc
index 5b1558c..6d822d9 100644
--- a/doc/src/manual/cowboy_websocket.asciidoc
+++ b/doc/src/manual/cowboy_websocket.asciidoc
@@ -126,7 +126,7 @@ timeout::
received first.
{error, Reason}::
- A socket error ocurred.
+ A socket error occurred.
== Types
@@ -285,6 +285,8 @@ normal circumstances if necessary.
== Changelog
+* *2.11*: Websocket over HTTP/2 is now considered stable.
+* *2.11*: HTTP/1.1 Websocket no longer traps exits by default.
* *2.8*: The `active_n` option was added.
* *2.7*: The commands based interface has been documented.
The old interface is now deprecated.