1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
[[req_body]]
== Reading the request body
The request body can be read using the Req object.
Cowboy will not attempt to read the body until requested.
You need to call the body reading functions in order to
retrieve it.
Cowboy will not cache the body, it is therefore only
possible to read it once.
You are not required to read it, however. If a body is
present and was not read, Cowboy will either cancel or
skip its download, depending on the protocol.
Cowboy provides functions for reading the body raw,
and read and parse form urlencoded or xref:multipart[multipart bodies].
The latter is covered in its own chapter.
=== Request body presence
Not all requests come with a body. You can check for
the presence of a request body with this function:
[source,erlang]
cowboy_req:has_body(Req).
It returns `true` if there is a body; `false` otherwise.
In practice, this function is rarely used. When the
method is `POST`, `PUT` or `PATCH`, the request body
is often required by the application, which should
just attempt to read it directly.
=== Request body length
You can obtain the length of the body:
[source,erlang]
Length = cowboy_req:body_length(Req).
Note that the length may not be known in advance. In
that case `undefined` will be returned. This can happen
with HTTP/1.1's chunked transfer-encoding, or HTTP/2
when no content-length was provided.
Cowboy will update the body length in the Req object
once the body has been read completely. A length will
always be returned when attempting to call this function
after reading the body completely.
=== Reading the body
You can read the entire body with one function call:
[source,erlang]
{ok, Data, Req} = cowboy_req:read_body(Req0).
Cowboy returns an `ok` tuple when the body has been
read fully.
By default, Cowboy will attempt to read up to 8MB
of data, for up to 15 seconds. The call will return
once Cowboy has read at least 8MB of data, or at
the end of the 15 seconds period.
These values can be customized. For example, to read
only up to 1MB for up to 5 seconds:
[source,erlang]
----
{ok, Data, Req} = cowboy_req:read_body(Req0,
#{length => 1000000, period => 5000}).
----
These two options can effectively be used to control
the rate of transmission of the request body.
It is also possible to asynchronously read the request
body using auto mode:
[source,erlang]
----
Ref = make_ref(),
cowboy_req:cast({read_body, self(), Ref, auto, infinity}, Req).
----
Cowboy will wait indefinitely for data and then send a
`request_body` message as soon as it has data available,
regardless of length.
[source,erlang]
----
receive
{request_body, Ref, nofin, Data} ->
do_something(Data);
{request_body, Ref, fin, _BodyLen, Data} ->
do_something(Data)
end.
----
Asynchronous reading of data pairs well with loop handlers.
=== Streaming the body
When the body is too large, the first call will return
a `more` tuple instead of `ok`. You can call the
function again to read more of the body, reading
it one chunk at a time.
[source,erlang]
----
read_body_to_console(Req0) ->
case cowboy_req:read_body(Req0) of
{ok, Data, Req} ->
io:format("~s", [Data]),
Req;
{more, Data, Req} ->
io:format("~s", [Data]),
read_body_to_console(Req)
end.
----
The `length` and `period` options can also be used.
They need to be passed for every call.
=== Reading a form urlencoded body
Cowboy provides a convenient function for reading and
parsing bodies sent as application/x-www-form-urlencoded.
[source,erlang]
{ok, KeyValues, Req} = cowboy_req:read_urlencoded_body(Req0).
This function returns a list of key/values, exactly like
the function `cowboy_req:parse_qs/1`.
The defaults for this function are different. Cowboy will
read for up to 64KB and up to 5 seconds. They can be modified:
[source,erlang]
----
{ok, KeyValues, Req} = cowboy_req:read_urlencoded_body(Req0,
#{length => 4096, period => 3000}).
----
|