aboutsummaryrefslogtreecommitdiffstats
path: root/doc/src/guide/req.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/guide/req.asciidoc')
-rw-r--r--doc/src/guide/req.asciidoc247
1 files changed, 247 insertions, 0 deletions
diff --git a/doc/src/guide/req.asciidoc b/doc/src/guide/req.asciidoc
new file mode 100644
index 0000000..09d442a
--- /dev/null
+++ b/doc/src/guide/req.asciidoc
@@ -0,0 +1,247 @@
+[[req]]
+== The Req object
+
+The Req object is this variable that you will use to obtain
+information about a request, read the body of the request
+and send a response.
+
+=== A special variable
+
+While we call it an "object", it is not an object in the
+OOP sense of the term. In fact it is completely opaque
+to you and the only way you can perform operations using
+it is by calling the functions from the `cowboy_req`
+module.
+
+Almost all the calls to the `cowboy_req` module will
+return an updated request object. Just like you would
+keep the updated `State` variable in a gen_server,
+you MUST keep the updated `Req` variable in a Cowboy
+handler. Cowboy will use this object to know whether
+a response has been sent when the handler has finished
+executing.
+
+The Req object allows accessing both immutable and
+mutable state. This means that calling some of the
+functions twice will not produce the same result.
+For example, when streaming the request body, the
+function will return the body by chunks, one at a
+time, until there is none left.
+
+=== Overview of the cowboy_req interface
+
+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
+
+When a client performs a request, it first sends a few required
+values. They are sent differently depending on the protocol
+being used, but the intent is the same. They indicate to the
+server the type of action it wants to do and how to locate
+the resource to perform it on.
+
+The method identifies the action. Standard methods include
+GET, HEAD, OPTIONS, PATCH, POST, PUT, DELETE. Method names
+are case sensitive.
+
+[source,erlang]
+Method = cowboy_req:method(Req).
+
+The host, port and path parts of the URL identify the resource
+being accessed. The host and port information may not be
+available if the client uses HTTP/1.0.
+
+[source,erlang]
+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.
+
+[source,erlang]
+Version = cowboy_req:version(Req).
+
+Do note however that clients claiming to implement one version
+of the protocol does not mean they implement it fully, or even
+properly.
+
+=== Bindings
+
+After routing the request, bindings are available. Bindings
+are these parts of the host or path that you chose to extract
+when defining the routes of your application.
+
+You can fetch a single binding. The value will be `undefined`
+if the binding doesn't exist.
+
+[source,erlang]
+Binding = cowboy_req:binding(my_binding, Req).
+
+If you need a different value when the binding doesn't exist,
+you can change the default.
+
+[source,erlang]
+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.
+
+[source,erlang]
+AllBindings = cowboy_req:bindings(Req).
+
+If you used `...` at the beginning of the route's pattern
+for the host, you can retrieve the matched part of the host.
+The value will be `undefined` otherwise.
+
+[source,erlang]
+HostInfo = cowboy_req:host_info(Req).
+
+Similarly, if you used `...` at the end of the route's
+pattern for the path, you can retrieve the matched part,
+or get `undefined` otherwise.
+
+[source,erlang]
+PathInfo = cowboy_req:path_info(Req).
+
+=== Query string
+
+The raw query string can be obtained directly.
+
+[source,erlang]
+Qs = cowboy_req:qs(Req).
+
+You can parse the query string and then use standard library
+functions to access individual values.
+
+[source,erlang]
+QsVals = cowboy_req:parse_qs(Req),
+{_, Lang} = lists:keyfind(<<"lang">>, 1, QsVals).
+
+You can match the query string into a map.
+
+[source,erlang]
+#{id := ID, lang := Lang} = cowboy_req:match_qs([id, lang], Req).
+
+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.
+
+[source,erlang]
+QsMap = cowboy_req:match_qs([{id, int}, {lang, nonempty}], Req).
+
+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.
+
+[source,erlang]
+#{lang := Lang} = cowboy_req:match_qs([{lang, [], <<"en-US">>}], Req).
+
+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.
+
+[source,erlang]
+URL = cowboy_req:url(Req).
+
+You can also obtain only the base of the URL, excluding the
+path and query string.
+
+[source,erlang]
+BaseURL = cowboy_req:host_url(Req).
+
+=== Headers
+
+Cowboy allows you to obtain the header values as string,
+or parsed into a more meaningful representation.
+
+This will get the string value of a header.
+
+[source,erlang]
+HeaderVal = cowboy_req:header(<<"content-type">>, Req).
+
+You can of course set a default in case the header is missing.
+
+[source,erlang]
+HeaderVal = cowboy_req:header(<<"content-type">>, Req, <<"text/plain">>).
+
+And also obtain all headers.
+
+[source,erlang]
+AllHeaders = cowboy_req:headers(Req).
+
+To parse the previous header, simply call `parse_header/{2,3}`
+where you would call `header/{2,3}` otherwise.
+
+[source,erlang]
+ParsedVal = cowboy_req:parse_header(<<"content-type">>, Req).
+
+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.
+
+[source,erlang]
+----
+ParsedVal = cowboy_req:parse_header(<<"content-type">>, Req,
+ {<<"text">>, <<"plain">>, []}).
+----
+
+The list of known headers and default values is defined in the
+manual.
+
+=== Meta
+
+Cowboy will sometimes associate some meta information with
+the request. Built-in meta values are listed in the manual
+for their respective modules.
+
+This will get a meta value. The returned value will be `undefined`
+if it isn't defined.
+
+[source,erlang]
+MetaVal = cowboy_req:meta(websocket_version, Req).
+
+You can change the default value if needed.
+
+[source,erlang]
+MetaVal = cowboy_req:meta(websocket_version, Req, 13).
+
+You can also define your own meta values. The name must be
+an `atom()`.
+
+[source,erlang]
+Req2 = cowboy_req:set_meta(the_answer, 42, Req).
+
+=== Peer
+
+You can obtain the peer address and port number. This is
+not necessarily the actual IP and port of the client, but
+rather the one of the machine that connected to the server.
+
+[source,erlang]
+{IP, Port} = cowboy_req:peer(Req).