mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Add sendfile support to cowboy_req:stream_body
It is now possible to stream one or more sendfile tuples. A simple example of what can now be done would be for example to build a tar file on the fly using the sendfile syscall for sending the files, or to support Range requests with more than one range with the sendfile syscall. When using cowboy_compress_h unfortunately we have to read the file in order to send it. More options will be added at a later time to make sure users don't read too much into memory. This is a new feature however so existing code is not affected. Also rework cowboy_http's data sending to be flatter.
This commit is contained in:
parent
29043aa7b4
commit
d7b7580b39
12 changed files with 219 additions and 100 deletions
|
@ -808,21 +808,35 @@ stream_reply(Status, Headers=#{}, Req=#{pid := Pid, streamid := StreamID})
|
|||
Pid ! {{Pid, StreamID}, {headers, Status, response_headers(Headers, Req)}},
|
||||
done_replying(Req, headers).
|
||||
|
||||
-spec stream_body(iodata(), fin | nofin, req()) -> ok.
|
||||
-spec stream_body(resp_body(), fin | nofin, req()) -> ok.
|
||||
%% Error out if headers were not sent.
|
||||
%% Don't send any body for HEAD responses.
|
||||
stream_body(_, _, #{method := <<"HEAD">>, has_sent_resp := headers}) ->
|
||||
ok;
|
||||
%% Don't send a message if the data is empty, except for the
|
||||
%% very last message with IsFin=fin.
|
||||
stream_body(Data, IsFin=nofin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
||||
%% very last message with IsFin=fin. When using sendfile this
|
||||
%% is converted to a data tuple, however.
|
||||
stream_body({sendfile, _, 0, _}, nofin, _) ->
|
||||
ok;
|
||||
stream_body({sendfile, _, 0, _}, IsFin=fin,
|
||||
#{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
||||
Pid ! {{Pid, StreamID}, {data, IsFin, <<>>}},
|
||||
ok;
|
||||
stream_body({sendfile, O, B, P}, IsFin,
|
||||
#{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
||||
when is_integer(O), O >= 0, is_integer(B), B > 0 ->
|
||||
Pid ! {{Pid, StreamID}, {data, IsFin, {sendfile, O, B, P}}},
|
||||
ok;
|
||||
stream_body(Data, IsFin=nofin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
||||
when not is_tuple(Data) ->
|
||||
case iolist_size(Data) of
|
||||
0 -> ok;
|
||||
_ ->
|
||||
Pid ! {{Pid, StreamID}, {data, IsFin, Data}},
|
||||
ok
|
||||
end;
|
||||
stream_body(Data, IsFin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers}) ->
|
||||
stream_body(Data, IsFin, #{pid := Pid, streamid := StreamID, has_sent_resp := headers})
|
||||
when not is_tuple(Data) ->
|
||||
Pid ! {{Pid, StreamID}, {data, IsFin, Data}},
|
||||
ok.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue