mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Check a return value of Transport:send/2 in cowboy_http
This commit is contained in:
parent
e612cbb40c
commit
f07e8ec347
1 changed files with 23 additions and 10 deletions
|
@ -254,7 +254,12 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport, opts=Opts,
|
||||||
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State);
|
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], State);
|
||||||
%% Messages pertaining to a stream.
|
%% Messages pertaining to a stream.
|
||||||
{{Pid, StreamID}, Msg} when Pid =:= self() ->
|
{{Pid, StreamID}, Msg} when Pid =:= self() ->
|
||||||
loop(info(State, StreamID, Msg));
|
try info(State, StreamID, Msg) of
|
||||||
|
NewState ->
|
||||||
|
loop(NewState)
|
||||||
|
catch throw:{send, Error} ->
|
||||||
|
terminate(State, Error)
|
||||||
|
end;
|
||||||
%% Exit signal from children.
|
%% Exit signal from children.
|
||||||
Msg = {'EXIT', Pid, _} ->
|
Msg = {'EXIT', Pid, _} ->
|
||||||
loop(down(State, Pid, Msg));
|
loop(down(State, Pid, Msg));
|
||||||
|
@ -1037,10 +1042,10 @@ commands(State0=#state{socket=Socket, transport=Transport, out_state=wait, strea
|
||||||
%% @todo 204 and 304 responses must not include a response body. (RFC7230 3.3.1, RFC7230 3.3.2)
|
%% @todo 204 and 304 responses must not include a response body. (RFC7230 3.3.1, RFC7230 3.3.2)
|
||||||
case Body of
|
case Body of
|
||||||
{sendfile, _, _, _} ->
|
{sendfile, _, _, _} ->
|
||||||
Transport:send(Socket, Response),
|
send(Transport, Socket, Response),
|
||||||
sendfile(State, Body);
|
sendfile(State, Body);
|
||||||
_ ->
|
_ ->
|
||||||
Transport:send(Socket, [Response, Body])
|
send(Transport, Socket, [Response, Body])
|
||||||
end,
|
end,
|
||||||
commands(State, StreamID, Tail);
|
commands(State, StreamID, Tail);
|
||||||
%% Send response headers and initiate chunked encoding or streaming.
|
%% Send response headers and initiate chunked encoding or streaming.
|
||||||
|
@ -1098,21 +1103,21 @@ commands(State0=#state{socket=Socket, transport=Transport, streams=Streams0, out
|
||||||
Stream0=#stream{method= <<"HEAD">>} ->
|
Stream0=#stream{method= <<"HEAD">>} ->
|
||||||
Stream0;
|
Stream0;
|
||||||
Stream0 when Size =:= 0, IsFin =:= fin, OutState =:= chunked ->
|
Stream0 when Size =:= 0, IsFin =:= fin, OutState =:= chunked ->
|
||||||
Transport:send(Socket, <<"0\r\n\r\n">>),
|
send(Transport, Socket, <<"0\r\n\r\n">>),
|
||||||
Stream0;
|
Stream0;
|
||||||
Stream0 when Size =:= 0 ->
|
Stream0 when Size =:= 0 ->
|
||||||
Stream0;
|
Stream0;
|
||||||
Stream0 when is_tuple(Data), OutState =:= chunked ->
|
Stream0 when is_tuple(Data), OutState =:= chunked ->
|
||||||
Transport:send(Socket, [integer_to_binary(Size, 16), <<"\r\n">>]),
|
send(Transport, Socket, [integer_to_binary(Size, 16), <<"\r\n">>]),
|
||||||
sendfile(State0, Data),
|
sendfile(State0, Data),
|
||||||
Transport:send(Socket,
|
send(Transport, Socket,
|
||||||
case IsFin of
|
case IsFin of
|
||||||
fin -> <<"\r\n0\r\n\r\n">>;
|
fin -> <<"\r\n0\r\n\r\n">>;
|
||||||
nofin -> <<"\r\n">>
|
nofin -> <<"\r\n">>
|
||||||
end),
|
end),
|
||||||
Stream0;
|
Stream0;
|
||||||
Stream0 when OutState =:= chunked ->
|
Stream0 when OutState =:= chunked ->
|
||||||
Transport:send(Socket, [
|
send(Transport, Socket, [
|
||||||
integer_to_binary(Size, 16), <<"\r\n">>, Data,
|
integer_to_binary(Size, 16), <<"\r\n">>, Data,
|
||||||
case IsFin of
|
case IsFin of
|
||||||
fin -> <<"\r\n0\r\n\r\n">>;
|
fin -> <<"\r\n0\r\n\r\n">>;
|
||||||
|
@ -1130,7 +1135,7 @@ commands(State0=#state{socket=Socket, transport=Transport, streams=Streams0, out
|
||||||
is_tuple(Data) ->
|
is_tuple(Data) ->
|
||||||
sendfile(State0, Data);
|
sendfile(State0, Data);
|
||||||
true ->
|
true ->
|
||||||
Transport:send(Socket, Data)
|
send(Transport, Socket, Data)
|
||||||
end,
|
end,
|
||||||
Stream0#stream{local_sent_size=SentSize}
|
Stream0#stream{local_sent_size=SentSize}
|
||||||
end,
|
end,
|
||||||
|
@ -1144,13 +1149,13 @@ commands(State=#state{socket=Socket, transport=Transport, streams=Streams, out_s
|
||||||
StreamID, [{trailers, Trailers}|Tail]) ->
|
StreamID, [{trailers, Trailers}|Tail]) ->
|
||||||
case stream_te(OutState, lists:keyfind(StreamID, #stream.id, Streams)) of
|
case stream_te(OutState, lists:keyfind(StreamID, #stream.id, Streams)) of
|
||||||
trailers ->
|
trailers ->
|
||||||
Transport:send(Socket, [
|
send(Transport, Socket, [
|
||||||
<<"0\r\n">>,
|
<<"0\r\n">>,
|
||||||
cow_http:headers(maps:to_list(Trailers)),
|
cow_http:headers(maps:to_list(Trailers)),
|
||||||
<<"\r\n">>
|
<<"\r\n">>
|
||||||
]);
|
]);
|
||||||
no_trailers ->
|
no_trailers ->
|
||||||
Transport:send(Socket, <<"0\r\n\r\n">>);
|
send(Transport, Socket, <<"0\r\n\r\n">>);
|
||||||
not_chunked ->
|
not_chunked ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
|
@ -1222,6 +1227,14 @@ headers_to_list(Headers0=#{<<"set-cookie">> := SetCookies}) ->
|
||||||
headers_to_list(Headers) ->
|
headers_to_list(Headers) ->
|
||||||
maps:to_list(Headers).
|
maps:to_list(Headers).
|
||||||
|
|
||||||
|
send(Transport, Socket, Data) ->
|
||||||
|
case Transport:send(Socket, Data) of
|
||||||
|
ok ->
|
||||||
|
ok;
|
||||||
|
{error, _Reason} = Error -> % handle 'timeout' as unrecoverable error too
|
||||||
|
erlang:throw({send, Error})
|
||||||
|
end.
|
||||||
|
|
||||||
%% We wrap the sendfile call into a try/catch because on OTP-20
|
%% We wrap the sendfile call into a try/catch because on OTP-20
|
||||||
%% and earlier a few different crashes could occur for sockets
|
%% and earlier a few different crashes could occur for sockets
|
||||||
%% that were closing or closed. For example a badarg in
|
%% that were closing or closed. For example a badarg in
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue