Skip to content

Commit

Permalink
Exit gracefully on {error,closed} when reading the PROXY header
Browse files Browse the repository at this point in the history
LH: Simplified the test a little.
  • Loading branch information
NelsonVides authored and essen committed Dec 21, 2023
1 parent f74b69c commit 5ef6455
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
16 changes: 9 additions & 7 deletions src/cowboy_clear.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,7 @@ start_link(Ref, Transport, Opts) ->

-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
connection_process(Parent, Ref, Transport, Opts) ->
ProxyInfo = case maps:get(proxy_header, Opts, false) of
true ->
{ok, ProxyInfo0} = ranch:recv_proxy_header(Ref, 1000),
ProxyInfo0;
false ->
undefined
end,
ProxyInfo = get_proxy_info(Ref, Opts),
{ok, Socket} = ranch:handshake(Ref),
%% Use cowboy_http2 directly only when 'http' is missing.
%% Otherwise switch to cowboy_http2 from cowboy_http.
Expand All @@ -58,3 +52,11 @@ init(Parent, Ref, Socket, Transport, ProxyInfo, Opts, Protocol) ->
supervisor -> process_flag(trap_exit, true)
end,
Protocol:init(Parent, Ref, Socket, Transport, ProxyInfo, Opts).

get_proxy_info(Ref, #{proxy_header := true}) ->
case ranch:recv_proxy_header(Ref, 1000) of
{ok, ProxyInfo} -> ProxyInfo;
{error, closed} -> exit({shutdown, closed})
end;
get_proxy_info(_, _) ->
undefined.
16 changes: 9 additions & 7 deletions src/cowboy_tls.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,7 @@ start_link(Ref, Transport, Opts) ->

-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
connection_process(Parent, Ref, Transport, Opts) ->
ProxyInfo = case maps:get(proxy_header, Opts, false) of
true ->
{ok, ProxyInfo0} = ranch:recv_proxy_header(Ref, 1000),
ProxyInfo0;
false ->
undefined
end,
ProxyInfo = get_proxy_info(Ref, Opts),
{ok, Socket} = ranch:handshake(Ref),
case ssl:negotiated_protocol(Socket) of
{ok, <<"h2">>} ->
Expand All @@ -54,3 +48,11 @@ init(Parent, Ref, Socket, Transport, ProxyInfo, Opts, Protocol) ->
supervisor -> process_flag(trap_exit, true)
end,
Protocol:init(Parent, Ref, Socket, Transport, ProxyInfo, Opts).

get_proxy_info(Ref, #{proxy_header := true}) ->
case ranch:recv_proxy_header(Ref, 1000) of
{ok, ProxyInfo} -> ProxyInfo;
{error, closed} -> exit({shutdown, closed})
end;
get_proxy_info(_, _) ->
undefined.
24 changes: 24 additions & 0 deletions test/proxy_header_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,30 @@ init_dispatch() ->

%% Tests.

fail_gracefully_on_disconnect(Config) ->
doc("Probing a port must not generate a crash"),
{ok, Socket} = gen_tcp:connect("localhost", config(port, Config),
[binary, {active, false}, {packet, raw}]),
timer:sleep(50),
Pid = case config(type, Config) of
tcp -> ct_helper:get_remote_pid_tcp(Socket);
%% We connect to a TLS port using a TCP socket so we need
%% to first obtain the remote pid of the TCP socket, which
%% is a TLS socket on the server, and then get the real
%% remote pid from its state.
ssl -> ct_helper:get_remote_pid_tls_state(ct_helper:get_remote_pid_tcp(Socket))
end,
Ref = erlang:monitor(process, Pid),
gen_tcp:close(Socket),
receive
{'DOWN', Ref, process, Pid, {shutdown, closed}} ->
ok;
{'DOWN', Ref, process, Pid, Reason} ->
error(Reason)
after 500 ->
error(timeout)
end.

v1_proxy_header(Config) ->
doc("Confirm we can read the proxy header at the start of the connection."),
ProxyInfo = #{
Expand Down

0 comments on commit 5ef6455

Please sign in to comment.