diff options
author | Loïc Hoguin <[email protected]> | 2018-11-09 17:42:37 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2018-11-09 17:42:37 +0100 |
commit | d7b7580b3913c17b404319cc4c153748d5e59194 (patch) | |
tree | 3026f38e4bcfdcb26d067a4e5aec6d401700c3cc /src/cowboy_req.erl | |
parent | 29043aa7b4d11e377bc76d453f592ea5a6df1f43 (diff) | |
download | cowboy-d7b7580b3913c17b404319cc4c153748d5e59194.tar.gz cowboy-d7b7580b3913c17b404319cc4c153748d5e59194.tar.bz2 cowboy-d7b7580b3913c17b404319cc4c153748d5e59194.zip |
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.
Diffstat (limited to 'src/cowboy_req.erl')
-rw-r--r-- | src/cowboy_req.erl | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 46bc62a..2c3de06 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -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. |