diff options
Diffstat (limited to 'doc/src/guide/req.ezdoc')
-rw-r--r-- | doc/src/guide/req.ezdoc | 156 |
1 files changed, 69 insertions, 87 deletions
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 |