mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Add streaming without chunking for HTTP/1.1
If content-length is set in the response headers we can skip chunked transfer-encoding.
This commit is contained in:
parent
69451dd98d
commit
f08f4610a0
4 changed files with 140 additions and 38 deletions
|
@ -220,6 +220,32 @@ do(<<"stream_body">>, Req0, Opts) ->
|
|||
cowboy_req:stream_body(<<0:800000>>, fin, Req0),
|
||||
{ok, Req0, Opts}
|
||||
end;
|
||||
do(<<"stream_body_content_length">>, Req0, Opts) ->
|
||||
case cowboy_req:binding(arg, Req0) of
|
||||
<<"fin0">> ->
|
||||
Req1 = cowboy_req:set_resp_header(<<"content-length">>, <<"12">>, Req0),
|
||||
Req = cowboy_req:stream_reply(200, Req1),
|
||||
cowboy_req:stream_body(<<"Hello world!">>, nofin, Req),
|
||||
cowboy_req:stream_body(<<>>, fin, Req),
|
||||
{ok, Req, Opts};
|
||||
<<"multiple">> ->
|
||||
Req1 = cowboy_req:set_resp_header(<<"content-length">>, <<"12">>, Req0),
|
||||
Req = cowboy_req:stream_reply(200, Req1),
|
||||
cowboy_req:stream_body(<<"Hello ">>, nofin, Req),
|
||||
cowboy_req:stream_body(<<"world">>, nofin, Req),
|
||||
cowboy_req:stream_body(<<"!">>, fin, Req),
|
||||
{ok, Req, Opts};
|
||||
<<"nofin">> ->
|
||||
Req1 = cowboy_req:set_resp_header(<<"content-length">>, <<"12">>, Req0),
|
||||
Req = cowboy_req:stream_reply(200, Req1),
|
||||
cowboy_req:stream_body(<<"Hello world!">>, nofin, Req),
|
||||
{ok, Req, Opts};
|
||||
<<"nofin-error">> ->
|
||||
Req1 = cowboy_req:set_resp_header(<<"content-length">>, <<"12">>, Req0),
|
||||
Req = cowboy_req:stream_reply(200, Req1),
|
||||
cowboy_req:stream_body(<<"Hello">>, nofin, Req),
|
||||
{ok, Req, Opts}
|
||||
end;
|
||||
do(<<"stream_trailers">>, Req0, Opts) ->
|
||||
case cowboy_req:binding(arg, Req0) of
|
||||
<<"large">> ->
|
||||
|
|
|
@ -146,6 +146,23 @@ do_decode(Headers, Body) ->
|
|||
_ -> Body
|
||||
end.
|
||||
|
||||
do_get_error(Path, Config) ->
|
||||
do_get_error(Path, [], Config).
|
||||
|
||||
do_get_error(Path, Headers, Config) ->
|
||||
ConnPid = gun_open(Config),
|
||||
Ref = gun:get(ConnPid, Path, [{<<"accept-encoding">>, <<"gzip">>}|Headers]),
|
||||
{response, IsFin, Status, RespHeaders} = gun:await(ConnPid, Ref),
|
||||
Result = case IsFin of
|
||||
nofin -> gun:await_body(ConnPid, Ref);
|
||||
fin -> {ok, <<>>}
|
||||
end,
|
||||
gun:close(ConnPid),
|
||||
case Result of
|
||||
{ok, RespBody} -> {Status, RespHeaders, do_decode(RespHeaders, RespBody)};
|
||||
_ -> Result
|
||||
end.
|
||||
|
||||
%% Tests: Request.
|
||||
|
||||
binding(Config) ->
|
||||
|
@ -856,6 +873,38 @@ stream_body_nofin(Config) ->
|
|||
{200, _, <<"Hello world!">>} = do_get("/resp/stream_body/nofin", Config),
|
||||
ok.
|
||||
|
||||
stream_body_content_length_multiple(Config) ->
|
||||
doc("Streamed body via multiple calls."),
|
||||
{200, _, <<"Hello world!">>} = do_get("/resp/stream_body_content_length/multiple", Config),
|
||||
ok.
|
||||
|
||||
stream_body_content_length_fin0(Config) ->
|
||||
doc("Streamed body with last chunk of size 0."),
|
||||
{200, _, <<"Hello world!">>} = do_get("/resp/stream_body_content_length/fin0", Config),
|
||||
ok.
|
||||
|
||||
stream_body_content_length_nofin(Config) ->
|
||||
doc("Unfinished streamed body."),
|
||||
{200, _, <<"Hello world!">>} = do_get("/resp/stream_body_content_length/nofin", Config),
|
||||
ok.
|
||||
|
||||
stream_body_content_length_nofin_error(Config) ->
|
||||
doc("Not all of body sent."),
|
||||
case config(protocol, Config) of
|
||||
http ->
|
||||
case do_get_error("/resp/stream_body_content_length/nofin-error", Config) of
|
||||
{200, Headers, <<"Hello">>} ->
|
||||
{_, <<"gzip">>} = lists:keyfind(<<"content-encoding">>, 1, Headers);
|
||||
{error, {closed, "The connection was lost."}} ->
|
||||
ok;
|
||||
{error, timeout} ->
|
||||
ok
|
||||
end;
|
||||
http2 ->
|
||||
%% @todo HTTP2 should have the same content-length checks
|
||||
ok
|
||||
end.
|
||||
|
||||
%% @todo Crash when calling stream_body after the fin flag has been set.
|
||||
%% @todo Crash when calling stream_body after calling reply.
|
||||
%% @todo Crash when calling stream_body before calling stream_reply.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue