Skip to content

Commit

Permalink
Add support for 431 response code
Browse files Browse the repository at this point in the history
Headers must be smaller than recbuf, but in some cases they won't be.  Simply returning 400 Bad Request with no indication is not helpful - header code 431 is designed for this - https://tools.ietf.org/html/rfc6585#section-5

This response code is not supported in the erlang httpd_util, so need to override the mapping of codes to response messages for this code to provide the supported return.
  • Loading branch information
martinsumner committed Jun 15, 2022
1 parent cefba88 commit dc176b1
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
18 changes: 11 additions & 7 deletions src/mochiweb_http.erl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ headers(Socket, Opts, Request, Headers, Body,
{tcp_closed = Error, _} ->
mochiweb_socket:close(Socket), exit({shutdown, Error});
{tcp_error, _, emsgsize} ->
handle_invalid_request(Socket, Opts, Request, Headers)
handle_invalid_request(Socket, Opts, Request, Headers, 431)
after ?HEADERS_RECV_TIMEOUT ->
mochiweb_socket:close(Socket), exit({shutdown, headers_recv_timeout})
end.
Expand All @@ -158,18 +158,22 @@ call_body(Body, Req) -> Body(Req).

-spec handle_invalid_request(term(), term()) -> no_return().
handle_invalid_request(Socket, Opts) ->
handle_invalid_request(Socket, Opts,
{'GET', {abs_path, "/"}, {0, 9}}, []).
handle_invalid_request(
Socket, Opts, {'GET', {abs_path, "/"}, {0, 9}}, []).

-spec handle_invalid_request(
term(), term(), term(), term()) -> no_return().
handle_invalid_request(Socket, Opts, Request, RevHeaders) ->
handle_invalid_request(Socket, Opts, Request, RevHeaders, 400).

-spec handle_invalid_request(term(), term(), term(),
term()) -> no_return().
-spec handle_invalid_request(
term(), term(), term(), term(), 400..431) -> no_return().

handle_invalid_request(Socket, Opts, Request,
RevHeaders) ->
RevHeaders, StatusCode) ->
{ReqM, _} = Req = new_request(Socket, Opts, Request,
RevHeaders),
ReqM:respond({400, [], []}, Req),
ReqM:respond({StatusCode, [], []}, Req),
mochiweb_socket:close(Socket),
exit({shutdown, invalid_request}).

Expand Down
4 changes: 4 additions & 0 deletions src/mochiweb_request.erl
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@ server_headers() ->
[{"Server", "MochiWeb/1.0 (" ++ (?QUIP) ++ ")"},
{"Date", mochiweb_clock:rfc1123()}].

make_code(431) ->
% HTTP Code 431 not yet supported in httpd_util
["431",
[" " | "Request Header Fields Too Large"]];
make_code(X) when is_integer(X) ->
[integer_to_list(X),
[" " | httpd_util:reason_phrase(X)]];
Expand Down
9 changes: 4 additions & 5 deletions test/mochiweb_http_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ has_acceptor_bug_tests(Server) ->
[{"1000 should be fine even with the bug",
?_assertEqual(false, (has_bug(Port, 1000)))},
{"10000 should trigger the bug if present",
?_assertEqual(false,
(has_bug(Port, 10000)))}].
?_assertNot((has_bug(Port, 10000)))}].

responder(Req) ->
mochiweb_request:respond({200,
Expand All @@ -37,6 +36,6 @@ has_bug(Port, Len) ->
{{"HTTP/1.1", 200, "OK"}, _,
"<html><body>Hello</body></html>"}} ->
false;
%% It is expected that the request will fail because the header is too long
{ok, {{"HTTP/1.1", 400, "Bad Request"}, _, []}} -> false
end.
{ok, {{"HTTP/1.1", 431, "Request Header Fields Too Large"}, _, []}} ->
false
end.

0 comments on commit dc176b1

Please sign in to comment.