Skip to content

Commit

Permalink
Improve the error when trying to send a 204/304 with a body
Browse files Browse the repository at this point in the history
  • Loading branch information
essen committed Jan 9, 2024
1 parent e4a78aa commit a40bab8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
23 changes: 14 additions & 9 deletions src/cowboy_req.erl
Original file line number Diff line number Diff line change
Expand Up @@ -813,20 +813,26 @@ reply(Status, Headers, SendFile = {sendfile, _, Len, _}, Req)
%% Neither status code must include a response body. (RFC7230 3.3)
reply(Status, Headers, Body, Req)
when Status =:= 204; Status =:= 304 ->
0 = iolist_size(Body),
do_reply(Status, Headers, Body, Req);
do_reply_ensure_no_body(Status, Headers, Body, Req);
reply(Status = <<"204",_/bits>>, Headers, Body, Req) ->
0 = iolist_size(Body),
do_reply(Status, Headers, Body, Req);
do_reply_ensure_no_body(Status, Headers, Body, Req);
reply(Status = <<"304",_/bits>>, Headers, Body, Req) ->
0 = iolist_size(Body),
do_reply(Status, Headers, Body, Req);
do_reply_ensure_no_body(Status, Headers, Body, Req);
reply(Status, Headers, Body, Req)
when is_integer(Status); is_binary(Status) ->
do_reply(Status, Headers#{
<<"content-length">> => integer_to_binary(iolist_size(Body))
}, Body, Req).

do_reply_ensure_no_body(Status, Headers, Body, Req) ->
case iolist_size(Body) of
0 ->
do_reply(Status, Headers, Body, Req);
_ ->
exit({response_error, payload_too_large,
'204 and 304 responses must not include a response body. (RFC7230 3.3)'})
end.

%% Don't send any body for HEAD responses. While the protocol code is
%% supposed to enforce this rule, we prefer to avoid copying too much
%% data around if we can avoid it.
Expand All @@ -851,12 +857,11 @@ stream_reply(_, _, #{has_sent_resp := _}) ->
%% 204 and 304 responses must NOT send a body. We therefore
%% transform the call to a full response and expect the user
%% to NOT call stream_body/3 afterwards. (RFC7230 3.3)
stream_reply(Status = 204, Headers=#{}, Req) ->
stream_reply(Status, Headers=#{}, Req)
when Status =:= 204; Status =:= 304 ->
reply(Status, Headers, <<>>, Req);
stream_reply(Status = <<"204",_/bits>>, Headers=#{}, Req) ->
reply(Status, Headers, <<>>, Req);
stream_reply(Status = 304, Headers=#{}, Req) ->
reply(Status, Headers, <<>>, Req);
stream_reply(Status = <<"304",_/bits>>, Headers=#{}, Req) ->
reply(Status, Headers, <<>>, Req);
stream_reply(Status, Headers=#{}, Req) when is_integer(Status); is_binary(Status) ->
Expand Down
4 changes: 2 additions & 2 deletions test/handlers/resp_h.erl
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ do(<<"reply4">>, Req0, Opts) ->
ct_helper:ignore(erlang, iolist_size, 1),
cowboy_req:reply(200, #{}, ok, Req0);
<<"204body">> ->
ct_helper:ignore(cowboy_req, reply, 4),
ct_helper:ignore(cowboy_req, do_reply_ensure_no_body, 4),
cowboy_req:reply(204, #{}, <<"OK">>, Req0);
<<"304body">> ->
ct_helper:ignore(cowboy_req, reply, 4),
ct_helper:ignore(cowboy_req, do_reply_ensure_no_body, 4),
cowboy_req:reply(304, #{}, <<"OK">>, Req0);
Status ->
cowboy_req:reply(binary_to_integer(Status), #{}, <<"OK">>, Req0)
Expand Down

0 comments on commit a40bab8

Please sign in to comment.