aboutsummaryrefslogtreecommitdiffstats
path: root/doc/src/guide
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2014-09-23 16:43:29 +0300
committerLoïc Hoguin <[email protected]>2014-09-23 16:43:29 +0300
commitf1c3b6d76f0c97e1ab927c288bb94891ae4c253b (patch)
tree5a14c007cdcb487032162b3ca96df648f521321a /doc/src/guide
parentb57f94661f5fd186f55eb0fead49849e0b1399d1 (diff)
downloadcowboy-f1c3b6d76f0c97e1ab927c288bb94891ae4c253b.tar.gz
cowboy-f1c3b6d76f0c97e1ab927c288bb94891ae4c253b.tar.bz2
cowboy-f1c3b6d76f0c97e1ab927c288bb94891ae4c253b.zip
Breaking update of the cowboy_req interface
Simplify the interface for most cowboy_req functions. They all return a single value except the four body reading functions. The reply functions now only return a Req value. Access functions do not return a Req anymore. Functions that used to cache results do not have a cache anymore. The interface for accessing query string and cookies has therefore been changed. There are now three query string functions: qs/1 provides access to the raw query string value; parse_qs/1 returns the query string as a list of key/values; match_qs/2 returns a map containing the values requested in the second argument, after applying constraints and default value. Similarly, there are two cookie functions: parse_cookies/1 and match_cookies/2. More match functions will be added in future commits. None of the functions return an error tuple anymore. It either works or crashes. Cowboy will attempt to provide an appropriate status code in the response of crashed handlers. As a result, the content decode function has its return value changed to a simple binary, and the body reading functions only return on success.
Diffstat (limited to 'doc/src/guide')
-rw-r--r--doc/src/guide/broken_clients.ezdoc3
-rw-r--r--doc/src/guide/constraints.ezdoc51
-rw-r--r--doc/src/guide/cookies.ezdoc41
-rw-r--r--doc/src/guide/getting_started.ezdoc2
-rw-r--r--doc/src/guide/hooks.ezdoc3
-rw-r--r--doc/src/guide/http_handlers.ezdoc4
-rw-r--r--doc/src/guide/http_req_life.ezdoc2
-rw-r--r--doc/src/guide/index.ezdoc1
-rw-r--r--doc/src/guide/loop_handlers.ezdoc6
-rw-r--r--doc/src/guide/multipart_req.ezdoc2
-rw-r--r--doc/src/guide/req.ezdoc156
-rw-r--r--doc/src/guide/req_body.ezdoc4
-rw-r--r--doc/src/guide/resp.ezdoc24
-rw-r--r--doc/src/guide/ws_handlers.ezdoc12
14 files changed, 184 insertions, 127 deletions
diff --git a/doc/src/guide/broken_clients.ezdoc b/doc/src/guide/broken_clients.ezdoc
index 26568a3..c508358 100644
--- a/doc/src/guide/broken_clients.ezdoc
+++ b/doc/src/guide/broken_clients.ezdoc
@@ -28,8 +28,7 @@ that will format the header names with the expected case.
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.
+ cowboy_req:reply(Status, Headers2, Body, Req).
```
Note that SPDY clients do not have that particular issue
diff --git a/doc/src/guide/constraints.ezdoc b/doc/src/guide/constraints.ezdoc
new file mode 100644
index 0000000..a05f489
--- /dev/null
+++ b/doc/src/guide/constraints.ezdoc
@@ -0,0 +1,51 @@
+::: Constraints
+
+Cowboy provides an optional constraints based validation feature
+when interacting with user input.
+
+Constraints are first used during routing. The router uses
+constraints to more accurately match bound values, allowing
+to create routes where a segment is an integer for example,
+and rejecting the others.
+
+Constraints are also used when performing a match operation
+on input data, like the query string or cookies. There, a
+default value can also be provided for optional values.
+
+Finally, constraints can be used to not only validate input,
+but also convert said input into proper Erlang terms, all in
+one step.
+
+:: Structure
+
+Constraints are provided as a list of fields and for each
+field a list of constraints for that field can be provided.
+
+Fields are either the name of the field; the name and
+one or more constraints; or the name, one or more constraints
+and a default value.
+
+When no default value is provided then the field is required.
+Otherwise the default value is used.
+
+All constraints for a field will be used to match its value
+in the order they are given. If the value is modified by a
+constraint, the next constraint receives the updated value.
+
+:: Built-in constraints
+
+|| Constraint Description
+|
+| int Convert binary value to integer
+| nonempty Ensures the binary value is non-empty
+
+:: Custom constraint
+
+In addition to the predefined constraints, Cowboy will accept
+a fun. This fun must accept one argument and return one of
+`true`, `{true, NewValue}` or `false`. The result indicates
+whether the value matches the constraint, and if it does it
+can optionally be modified. This allows converting the value
+to a more appropriate Erlang term.
+
+Note that constraint functions SHOULD be pure and MUST NOT crash.
diff --git a/doc/src/guide/cookies.ezdoc b/doc/src/guide/cookies.ezdoc
index fe9246c..459d4d8 100644
--- a/doc/src/guide/cookies.ezdoc
+++ b/doc/src/guide/cookies.ezdoc
@@ -116,22 +116,47 @@ As we said, the client sends cookies with every request.
But unlike the server, the client only sends the cookie
name and value.
-You can read the value of a cookie.
+Cowboy provides two different ways to read cookies. You
+can either parse them as a list of key/value pairs, or
+match them into a map, optionally applying constraints
+to the values or providing a default if they are missing.
+
+You can parse the cookies and then use standard library
+functions to access individual values.
+
+``` erlang
+Cookies = cowboy_req:parse_cookies(Req),
+{_, Lang} = lists:keyfind(<<"lang">>, 1, Cookies).
+```
+
+You can match the cookies into a map.
``` erlang
-{CookieVal, Req2} = cowboy_req:cookie(<<"lang">>, Req).
+#{id := ID, lang := Lang} = cowboy_req:match_cookies(Req, [id, lang]).
```
-You can also get a default value returned when the cookie
-isn't set.
+You can use constraints to validate the values while matching
+them. The following snippet will crash if the `id` cookie is
+not an integer number or if the `lang` cookie is empty. Additionally
+the `id` cookie value will be converted to an integer term, saving
+you a conversion step.
``` erlang
-{CookieVal, Req2} = cowboy_req:cookie(<<"lang">>, Req, <<"fr">>).
+CookiesMap = cowboy_req:match_cookies(Req, [{id, int}, {lang, nonempty}]).
```
-And you can obtain all cookies at once as a list of
-key/value tuples.
+Note that if two cookies share the same name, then the map value
+will be a list of the two cookie values.
+
+Read more about ^constraints^.
+
+A default value can be provided. The default will be used
+if the `lang` cookie is not found. It will not be used if
+the cookie is found but has an empty value.
``` erlang
-{AllCookies, Req2} = cowboy_req:cookies(Req).
+#{lang := Lang} = cowboy_req:match_cookies(Req, [{lang, [], <<"en-US">>}]).
```
+
+If no default is provided and the value is missing, the
+query string is deemed invalid and the process will crash.
diff --git a/doc/src/guide/getting_started.ezdoc b/doc/src/guide/getting_started.ezdoc
index f0a701d..34f02dc 100644
--- a/doc/src/guide/getting_started.ezdoc
+++ b/doc/src/guide/getting_started.ezdoc
@@ -154,7 +154,7 @@ the `handle/2` function like this to send a reply.
``` erlang
handle(Req, State=#state{}) ->
- {ok, Req2} = cowboy_req:reply(200,
+ Req2 = cowboy_req:reply(200,
[{<<"content-type">>, <<"text/plain">>}],
<<"Hello Erlang!">>,
Req),
diff --git a/doc/src/guide/hooks.ezdoc b/doc/src/guide/hooks.ezdoc
index edef971..e835a6f 100644
--- a/doc/src/guide/hooks.ezdoc
+++ b/doc/src/guide/hooks.ezdoc
@@ -73,8 +73,7 @@ custom_404_hook(404, Headers, <<>>, Req) ->
Body = <<"404 Not Found.">>,
Headers2 = lists:keyreplace(<<"content-length">>, 1, Headers,
{<<"content-length">>, integer_to_list(byte_size(Body))}),
- {ok, Req2} = cowboy_req:reply(404, Headers2, Body, Req),
- Req2;
+ cowboy_req:reply(404, Headers2, Body, Req);
custom_404_hook(_, _, _, Req) ->
Req.
```
diff --git a/doc/src/guide/http_handlers.ezdoc b/doc/src/guide/http_handlers.ezdoc
index 9a450a6..9c6e41d 100644
--- a/doc/src/guide/http_handlers.ezdoc
+++ b/doc/src/guide/http_handlers.ezdoc
@@ -61,7 +61,7 @@ continue with the handler code, so we use the
init(_Type, Req, Opts) ->
case lists:keyfind(lang, 1, Opts) of
false ->
- {ok, Req2} = cowboy_req:reply(500, [
+ Req2 = cowboy_req:reply(500, [
{<<"content-type">>, <<"text/plain">>}
], "Missing option 'lang'.", Req),
{shutdown, Req2, no_state};
@@ -110,7 +110,7 @@ The following handle function will send a fairly original response.
``` erlang
handle(Req, State) ->
- {ok, Req2} = cowboy_req:reply(200, [
+ Req2 = cowboy_req:reply(200, [
{<<"content-type">>, <<"text/plain">>}
], <<"Hello World!">>, Req),
{ok, Req2, State}.
diff --git a/doc/src/guide/http_req_life.ezdoc b/doc/src/guide/http_req_life.ezdoc
index 5fd8486..ffe5dfa 100644
--- a/doc/src/guide/http_req_life.ezdoc
+++ b/doc/src/guide/http_req_life.ezdoc
@@ -80,7 +80,7 @@ as the reply is sent.
This snippet will force Cowboy to close the connection.
``` erlang
-{ok, Req2} = cowboy_req:reply(200, [
+Req2 = cowboy_req:reply(200, [
{<<"connection">>, <<"close">>},
], <<"Closing the socket in 3.. 2.. 1..">>, Req).
```
diff --git a/doc/src/guide/index.ezdoc b/doc/src/guide/index.ezdoc
index 38b2ac0..300cea8 100644
--- a/doc/src/guide/index.ezdoc
+++ b/doc/src/guide/index.ezdoc
@@ -15,6 +15,7 @@ best use of Cowboy for writing powerful web applications.
* ^"The life of a request^http_req_life
* ^"Routing^routing
+* ^"Constraints^constraints
* ^"Handling plain HTTP requests^http_handlers
* ^"The Req object^req
* ^"Reading the request body^req_body
diff --git a/doc/src/guide/loop_handlers.ezdoc b/doc/src/guide/loop_handlers.ezdoc
index fba4feb..b1c033f 100644
--- a/doc/src/guide/loop_handlers.ezdoc
+++ b/doc/src/guide/loop_handlers.ezdoc
@@ -60,7 +60,7 @@ message otherwise.
``` erlang
info({reply, Body}, Req, State) ->
- {ok, Req2} = cowboy_req:reply(200, [], Body, Req),
+ Req2 = cowboy_req:reply(200, [], Body, Req),
{ok, Req2, State};
info(_Msg, Req, State) ->
{loop, Req, State, hibernate}.
@@ -95,13 +95,13 @@ and the loop is stopped by sending an `eof` message.
``` erlang
init(_Type, Req, _Opts) ->
- {ok, Req2} = cowboy_req:chunked_reply(200, [], Req),
+ 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),
+ cowboy_req:chunk(Chunk, Req),
{loop, Req, State};
info(_Msg, Req, State) ->
{loop, Req, State}.
diff --git a/doc/src/guide/multipart_req.ezdoc b/doc/src/guide/multipart_req.ezdoc
index a807e48..21762f6 100644
--- a/doc/src/guide/multipart_req.ezdoc
+++ b/doc/src/guide/multipart_req.ezdoc
@@ -17,7 +17,7 @@ You can quickly figure out if a multipart message
has been sent by parsing the `content-type` header.
``` erlang
-{ok, {<<"multipart">>, <<"form-data">>, _}, Req2}
+{<<"multipart">>, <<"form-data">>, _}
= cowboy_req:parse_header(<<"content-type">>, Req).
```
diff --git a/doc/src/guide/req.ezdoc b/doc/src/guide/req.ezdoc
index 9501158..1349af3 100644
--- a/doc/src/guide/req.ezdoc
+++ b/doc/src/guide/req.ezdoc
@@ -27,47 +27,22 @@ For example, when streaming the request body, the
function will return the body by chunks, one at a
time, until there is none left.
-It also caches the result of operations performed
-on the immutable state. That means that some calls
-will give a result much faster when called many times.
-
:: Overview of the cowboy_req interface
-The `cowboy_req` interface is divided in four groups
-of functions, each having a well defined return type
-signature common to the entire group.
-
-The first group, access functions, will always return
-`{Value, Req}`. The group includes all the following
-functions: `binding/{2,3}`, `bindings/1`, `body_length/1`,
-`cookie/{2,3}`, `cookies/1`, `header/{2,3}`, `headers/1`,
-`host/1`, `host_info/1`, `host_url/1`, `meta/{2,3}`,
-`method/1`, `path/1`, `path_info/1`, `peer/1`, `port/1`,
-`qs/1`, `qs_val/{2,3}`, `qs_vals/1`, `url/1`, `version/1`.
-
-The second group, question functions, will always return
-a `boolean()`. The group includes the following three
-functions: `has_body/1`, `has_resp_body/1`, `has_resp_header/2`.
-
-The third group contains the functions that manipulate
-the socket or perform operations that may legitimately fail.
-They may return `{Result, Req}`, `{Result, Value, Req}`
-or `{error, atom()}`. This includes the following functions:
-`body/{1,2}`, `body_qs/{1,2}`, `chunked_reply/{2,3}`,
-`parse_header/{2,3}`, `part/{1,2}`, `part_body/{1,2}`
-and `reply/{2,3,4}`. Finally, the group also includes the
-`chunk/2` and `continue/1` functions which always return `ok`.
-
-The final group modifies the Req object state without
-performing any immediate operations. As these functions
-can't fail, they always return a new `Req` directly.
-This includes the following functions: `compact/1`,
-`delete_resp_header/2`, `set_meta/3`, `set_resp_body/2`,
-`set_resp_body_fun/{2,3}`, `set_resp_cookie/4`, `set_resp_header/3`.
-
-This chapter covers most of the first group, plus a few other
-functions. The next few chapters cover cookies handling, reading
-the request body and sending a response.
+With the exception of functions manipulating the request
+body, all functions return a single value. Depending on
+the function this can be the requested value (method,
+host, path, ...), a boolean (has_body, has_resp_header...)
+a new Req object (set_resp_body, set_resp_header...), or
+simply the atom `ok` (chunk, continue, ...).
+
+The request body reading functions may return `{Result, Req}`
+or `{Result, Value, Req}`. The functions in this category
+are `body/{1,2}`, `body_qs/{1,2}`, `part/{1,2}`, `part_body/{1,2}`.
+
+This chapter covers the access functions mainly. Cookies,
+request body and response functions are covered in their
+own chapters.
:: Request
@@ -82,7 +57,7 @@ GET, HEAD, OPTIONS, PATCH, POST, PUT, DELETE. Method names
are case sensitive.
``` erlang
-{Method, Req2} = cowboy_req:method(Req).
+Method = cowboy_req:method(Req).
```
The host, port and path parts of the URL identify the resource
@@ -90,15 +65,15 @@ being accessed. The host and port information may not be
available if the client uses HTTP/1.0.
``` erlang
-{Host, Req2} = cowboy_req:host(Req),
-{Port, Req3} = cowboy_req:port(Req2),
-{Path, Req4} = cowboy_req:path(Req3).
+Host = cowboy_req:host(Req),
+Port = cowboy_req:port(Req),
+Path = cowboy_req:path(Req).
```
The version used by the client can of course also be obtained.
``` erlang
-{Version, Req2} = cowboy_req:version(Req).
+Version = cowboy_req:version(Req).
```
Do note however that clients claiming to implement one version
@@ -115,21 +90,21 @@ You can fetch a single binding. The value will be `undefined`
if the binding doesn't exist.
``` erlang
-{Binding, Req2} = cowboy_req:binding(my_binding, Req).
+Binding = cowboy_req:binding(my_binding, Req).
```
If you need a different value when the binding doesn't exist,
you can change the default.
``` erlang
-{Binding, Req2} = cowboy_req:binding(my_binding, Req, 42).
+Binding = cowboy_req:binding(my_binding, Req, 42).
```
You can also obtain all bindings in one call. They will be
returned as a list of key/value tuples.
``` erlang
-{AllBindings, Req2} = cowboy_req:bindings(Req).
+AllBindings = cowboy_req:bindings(Req).
```
If you used `...` at the beginning of the route's pattern
@@ -137,7 +112,7 @@ for the host, you can retrieve the matched part of the host.
The value will be `undefined` otherwise.
``` erlang
-{HostInfo, Req2} = cowboy_req:host_info(Req).
+HostInfo = cowboy_req:host_info(Req).
```
Similarly, if you used `...` at the end of the route's
@@ -145,49 +120,70 @@ pattern for the path, you can retrieve the matched part,
or get `undefined` otherwise.
``` erlang
-{PathInfo, Req2} = cowboy_req:path_info(Req).
+PathInfo = cowboy_req:path_info(Req).
```
:: Query string
-The query string can be obtained directly.
+The raw query string can be obtained directly.
+
+``` erlang
+Qs = cowboy_req:qs(Req).
+```
+
+You can parse the query string and then use standard library
+functions to access individual values.
``` erlang
-{Qs, Req2} = cowboy_req:qs(Req).
+QsVals = cowboy_req:parse_qs(Req),
+{_, Lang} = lists:keyfind(<<"lang">>, 1, QsVals).
```
-You can also requests only one value.
+You can match the query string into a map.
``` erlang
-{QsVal, Req2} = cowboy_req:qs_val(<<"lang">>, Req).
+#{id := ID, lang := Lang} = cowboy_req:match_qs(Req, [id, lang]).
```
-If that value is optional, you can define a default to simplify
-your task.
+You can use constraints to validate the values while matching
+them. The following snippet will crash if the `id` value is
+not an integer number or if the `lang` value is empty. Additionally
+the `id` value will be converted to an integer term, saving
+you a conversion step.
``` erlang
-{QsVal, Req2} = cowboy_req:qs_val(<<"lang">>, Req, <<"en">>).
+QsMap = cowboy_req:match_qs(Req, [{id, int}, {lang, nonempty}]).
```
-Finally, you can obtain all query string values.
+Note that in the case of duplicate query string keys, the map
+value will become a list of the different values.
+
+Read more about ^constraints^.
+
+A default value can be provided. The default will be used
+if the `lang` key is not found. It will not be used if
+the key is found but has an empty value.
``` erlang
-{AllValues, Req2} = cowboy_req:qs_vals(Req).
+#{lang := Lang} = cowboy_req:match_qs(Req, [{lang, [], <<"en-US">>}]).
```
+If no default is provided and the value is missing, the
+query string is deemed invalid and the process will crash.
+
:: Request URL
You can reconstruct the full URL of the resource.
``` erlang
-{URL, Req2} = cowboy_req:url(Req).
+URL = cowboy_req:url(Req).
```
You can also obtain only the base of the URL, excluding the
path and query string.
``` erlang
-{BaseURL, Req2} = cowboy_req:host_url(Req).
+BaseURL = cowboy_req:host_url(Req).
```
:: Headers
@@ -198,57 +194,43 @@ or parsed into a more meaningful representation.
This will get the string value of a header.
``` erlang
-{HeaderVal, Req2} = cowboy_req:header(<<"content-type">>, Req).
+HeaderVal = cowboy_req:header(<<"content-type">>, Req).
```
You can of course set a default in case the header is missing.
``` erlang
-{HeaderVal, Req2}
+HeaderVal
= cowboy_req:header(<<"content-type">>, Req, <<"text/plain">>).
```
And also obtain all headers.
``` erlang
-{AllHeaders, Req2} = cowboy_req:headers(Req).
+AllHeaders = cowboy_req:headers(Req).
```
To parse the previous header, simply call `parse_header/{2,3}`
-where you would call `header/{2,3}` otherwise. Note that the
-return value changes and includes the result of the operation
-as the first element of the returned tuple. A successful parse
-returns `ok`.
-
-``` erlang
-{ok, ParsedVal, Req2} = cowboy_req:parse_header(<<"content-type">>, Req).
-```
-
-When Cowboy doesn't know how to parse the given header, the
-result of the operation will be `undefined` and the string value
-will be returned instead.
+where you would call `header/{2,3}` otherwise.
``` erlang
-{undefined, HeaderVal, Req2}
- = cowboy_req:parse_header(<<"unicorn-header">>, Req).
+ParsedVal = cowboy_req:parse_header(<<"content-type">>, Req).
```
-When parsing fails, `{error, Reason}` is returned instead.
+Cowboy will crash if it doesn't know how to parse the given
+header, or if the value is invalid.
You can of course define a default value. Note that the default
value you specify here is the parsed value you'd like to get
by default.
``` erlang
-{ok, ParsedVal, Req2}
- = cowboy_req:parse_header(<<"content-type">>, Req,
- {<<"text">>, <<"plain">>, []}).
+ParsedVal = cowboy_req:parse_header(<<"content-type">>, Req,
+ {<<"text">>, <<"plain">>, []}).
```
The list of known headers and default values is defined in the
-manual. Also note that the result of parsing is cached, so
-calling this function multiple times for the same values will
-not have a significant performance impact.
+manual.
:: Meta
@@ -260,13 +242,13 @@ This will get a meta value. The returned value will be `undefined`
if it isn't defined.
``` erlang
-{MetaVal, Req2} = cowboy_req:meta(websocket_version, Req).
+MetaVal = cowboy_req:meta(websocket_version, Req).
```
You can change the default value if needed.
``` erlang
-{MetaVal, Req2} = cowboy_req:meta(websocket_version, Req, 13).
+MetaVal = cowboy_req:meta(websocket_version, Req, 13).
```
You can also define your own meta values. The name must be
@@ -283,7 +265,7 @@ not necessarily the actual IP and port of the client, but
rather the one of the machine that connected to the server.
``` erlang
-{{IP, Port}, Req2} = cowboy_req:peer(Req).
+{IP, Port} = cowboy_req:peer(Req).
```
:: Reducing the memory footprint
diff --git a/doc/src/guide/req_body.ezdoc b/doc/src/guide/req_body.ezdoc
index 44f32f8..8864035 100644
--- a/doc/src/guide/req_body.ezdoc
+++ b/doc/src/guide/req_body.ezdoc
@@ -37,7 +37,7 @@ You can obtain the body length if it was sent with the
request.
``` erlang
-{Length, Req2} = cowboy_req:body_length(Req).
+Length = cowboy_req:body_length(Req).
```
The value returned will be `undefined` if the length
@@ -123,7 +123,7 @@ ignored.
The following example shows how to set both options.
``` erlang
-{ok, Req2} = cowboy_req:body(Req, [
+{ok, Data, Req2} = cowboy_req:body(Req, [
{transfer_decode, fun transfer_decode/2, TransferState},
{content_decode, fun content_decode/1}
]).
diff --git a/doc/src/guide/resp.ezdoc b/doc/src/guide/resp.ezdoc
index 28f2544..009756a 100644
--- a/doc/src/guide/resp.ezdoc
+++ b/doc/src/guide/resp.ezdoc
@@ -16,7 +16,7 @@ Cowboy will make sure to send the mandatory headers with
the response.
``` erlang
-{ok, Req2} = cowboy_req:reply(200, Req).
+Req2 = cowboy_req:reply(200, Req).
```
You can define headers to be sent with the response. Note
@@ -24,7 +24,7 @@ that header names must be lowercase. Again, Cowboy will
make sure to send the mandatory headers with the response.
``` erlang
-{ok, Req2} = cowboy_req:reply(303, [
+Req2 = cowboy_req:reply(303, [
{<<"location">>, <<"http://ninenines.eu">>}
], Req).
```
@@ -35,7 +35,7 @@ by Cowboy. For example, you can advertise yourself as a
different server.
``` erlang
-{ok, Req2} = cowboy_req:reply(200, [
+Req2 = cowboy_req:reply(200, [
{<<"server">>, <<"yaws">>}
], Req).
```
@@ -49,7 +49,7 @@ We recommend that you set the content-type header so the
client may know how to read the body.
``` erlang
-{ok, Req2} = cowboy_req:reply(200, [
+Req2 = cowboy_req:reply(200, [
{<<"content-type">>, <<"text/plain">>}
], "Hello world!", Req).
```
@@ -57,7 +57,7 @@ client may know how to read the body.
Here is the same example but sending HTML this time.
``` erlang
-{ok, Req2} = cowboy_req:reply(200, [
+Req2 = cowboy_req:reply(200, [
{<<"content-type">>, <<"text/html">>}
], "<html><head>Hello world!</head><body><p>Hats off!</p></body></html>", Req).
```
@@ -71,10 +71,10 @@ initiate the reply by sending the response status code.
Then you can send the body in chunks of arbitrary size.
``` erlang
-{ok, Req2} = cowboy_req:chunked_reply(200, Req),
-ok = cowboy_req:chunk("Hello...", Req2),
-ok = cowboy_req:chunk("chunked...", Req2),
-ok = cowboy_req:chunk("world!!", Req2).
+Req2 = cowboy_req:chunked_reply(200, Req),
+cowboy_req:chunk("Hello...", Req2),
+cowboy_req:chunk("chunked...", Req2),
+cowboy_req:chunk("world!!", Req2).
```
You should make sure to match on `ok` as an error may be
@@ -85,11 +85,11 @@ a content-type header, it is still recommended. You can
set this header or any other just like for normal replies.
``` erlang
-{ok, Req2} = cowboy_req:chunked_reply(200, [
+Req2 = cowboy_req:chunked_reply(200, [
{<<"content-type">>, <<"text/html">>}
], Req),
-ok = cowboy_req:chunk("<html><head>Hello world!</head>", Req2),
-ok = cowboy_req:chunk("<body><p>Hats off!</p></body></html>", Req2).
+cowboy_req:chunk("<html><head>Hello world!</head>", Req2),
+cowboy_req:chunk("<body><p>Hats off!</p></body></html>", Req2).
```
Note that the reply and each chunk following it are sent
diff --git a/doc/src/guide/ws_handlers.ezdoc b/doc/src/guide/ws_handlers.ezdoc
index 9c3e2b7..1c84b98 100644
--- a/doc/src/guide/ws_handlers.ezdoc
+++ b/doc/src/guide/ws_handlers.ezdoc
@@ -68,16 +68,16 @@ the connection, assuming no correct subprotocol was found.
``` erlang
websocket_init(_Type, Req, _Opts) ->
case cowboy_req:parse_header(<<"sec-websocket-protocol">>, Req) of
- {ok, undefined, Req2} ->
+ undefined ->
{ok, Req, #state{}};
- {ok, Subprotocols, Req2} ->
+ Subprotocols ->
case lists:keymember(<<"mychat2">>, 1, Subprotocols) of
true ->
- Req3 = cowboy_req:set_resp_header(<<"sec-websocket-protocol">>,
- <<"mychat2">>, Req2),
- {ok, Req3, #state{}};
+ Req2 = cowboy_req:set_resp_header(<<"sec-websocket-protocol">>,
+ <<"mychat2">>, Req),
+ {ok, Req2, #state{}};
false ->
- {shutdown, Req2}
+ {shutdown, Req}
end
end.
```