读取请求主体
可以使用Req对象读取请求主体。
Cowboy不会试图读取主体,除非有人要求。您需要调用主体读取函数来检索它。
Cowboy不会缓存主体,因此只能读取一次。
但是,你不需要阅读它。如果有主体存在但没有被读取,Cowboy会取消或跳过它的下载,这取决于协议。
Cowboy提供了一些函数来读取主体原始信息,并从urlencoded或多部分主体中读取和解析。后者在它自己的章节中有讨论。
请求主体的存在
并不是所有的请求都伴随着一个主体。你可以用这个函数来检查请求体是否存在:
cowboy_req:has_body(Req).
如果存在主体则返回true;否则错误。
在实际操作中,很少使用这个函数。当方法是POST、PUT或PATCH时,应用程序通常需要请求主体,它应该尝试直接读取请求主体。
请求主体的长度
你可以得到主体的长度:
Length = cowboy_req:body_length(Req).
注意,长度可能不会提前知道。在这种情况下,undefined将被返回。这种情况会发生在HTTP/1.1的分块传输编码中,或者HTTP/2没有提供内容长度时。
一旦主体被完全读取,Cowboy将更新Req对象中的主体长度。当完全读取主体后试图调用这个函数时,将总是返回一个长度。
读取主体
你可以通过一个函数调用来读取整个函数主体:
{ok, Data, Req} = cowboy_req:read_body(Req0).
当完整读取主体时,Cowboy返回一个ok元组。
默认情况下,Cowboy将尝试读取最多8MB的数据,持续15秒。一旦Cowboy读取了至少8MB的数据,或者在15秒的时间结束时,该调用将返回。
这些值可以自定义。例如,在5秒内只读1MB:
{ok, Data, Req} = cowboy_req:read_body(Req0,
#{length => 1000000, period => 5000}).
你也可以禁用长度限制:
{ok, Data, Req} = cowboy_req:read_body(Req0, #{length => infinity}).
这使得函数等待15秒,并返回在这段时间内到达的任何内容。对于面向公众的应用程序,不建议这样做。
这两个选项可以有效地用来控制请求主体的传输速率。
流主体
当函数体太大时,第一次调用将返回一个更大的元组,而不是ok。您可以再次调用该函数来读取主体的更多内容,每次读取一个数据块。
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.
也可以使用长度和周期选项。每次call都要传递这些信息。
读取表单的urlencoded主体
Cowboy提供了一个方便的函数来读取和解析作为application/x-www-form-urlencoded发送的主体。
{ok, KeyValues, Req} = cowboy_req:read_urlencoded_body(Req0).
这个函数返回一个键值列表,就像函数cowboy_req:parse_qs/1一样。
这个函数的默认值是不同的。Cowboy的读取时间可达64KB,最长可达5秒。它们可以被修改:
{ok, KeyValues, Req} = cowboy_req:read_urlencoded_body(Req0,
#{length => 4096, period => 3000}).