mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Exit gracefully on {error,closed} when reading the PROXY header
LH: Simplified the test a little.
This commit is contained in:
parent
f74b69c3ed
commit
5ef64557b5
3 changed files with 42 additions and 14 deletions
|
@ -33,13 +33,7 @@ start_link(Ref, Transport, Opts) ->
|
||||||
|
|
||||||
-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
|
-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
|
||||||
connection_process(Parent, Ref, Transport, Opts) ->
|
connection_process(Parent, Ref, Transport, Opts) ->
|
||||||
ProxyInfo = case maps:get(proxy_header, Opts, false) of
|
ProxyInfo = get_proxy_info(Ref, Opts),
|
||||||
true ->
|
|
||||||
{ok, ProxyInfo0} = ranch:recv_proxy_header(Ref, 1000),
|
|
||||||
ProxyInfo0;
|
|
||||||
false ->
|
|
||||||
undefined
|
|
||||||
end,
|
|
||||||
{ok, Socket} = ranch:handshake(Ref),
|
{ok, Socket} = ranch:handshake(Ref),
|
||||||
%% Use cowboy_http2 directly only when 'http' is missing.
|
%% Use cowboy_http2 directly only when 'http' is missing.
|
||||||
%% Otherwise switch to cowboy_http2 from cowboy_http.
|
%% Otherwise switch to cowboy_http2 from cowboy_http.
|
||||||
|
@ -58,3 +52,11 @@ init(Parent, Ref, Socket, Transport, ProxyInfo, Opts, Protocol) ->
|
||||||
supervisor -> process_flag(trap_exit, true)
|
supervisor -> process_flag(trap_exit, true)
|
||||||
end,
|
end,
|
||||||
Protocol:init(Parent, Ref, Socket, Transport, ProxyInfo, Opts).
|
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.
|
||||||
|
|
|
@ -33,13 +33,7 @@ start_link(Ref, Transport, Opts) ->
|
||||||
|
|
||||||
-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
|
-spec connection_process(pid(), ranch:ref(), module(), cowboy:opts()) -> ok.
|
||||||
connection_process(Parent, Ref, Transport, Opts) ->
|
connection_process(Parent, Ref, Transport, Opts) ->
|
||||||
ProxyInfo = case maps:get(proxy_header, Opts, false) of
|
ProxyInfo = get_proxy_info(Ref, Opts),
|
||||||
true ->
|
|
||||||
{ok, ProxyInfo0} = ranch:recv_proxy_header(Ref, 1000),
|
|
||||||
ProxyInfo0;
|
|
||||||
false ->
|
|
||||||
undefined
|
|
||||||
end,
|
|
||||||
{ok, Socket} = ranch:handshake(Ref),
|
{ok, Socket} = ranch:handshake(Ref),
|
||||||
case ssl:negotiated_protocol(Socket) of
|
case ssl:negotiated_protocol(Socket) of
|
||||||
{ok, <<"h2">>} ->
|
{ok, <<"h2">>} ->
|
||||||
|
@ -54,3 +48,11 @@ init(Parent, Ref, Socket, Transport, ProxyInfo, Opts, Protocol) ->
|
||||||
supervisor -> process_flag(trap_exit, true)
|
supervisor -> process_flag(trap_exit, true)
|
||||||
end,
|
end,
|
||||||
Protocol:init(Parent, Ref, Socket, Transport, ProxyInfo, Opts).
|
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.
|
||||||
|
|
|
@ -71,6 +71,30 @@ init_dispatch() ->
|
||||||
|
|
||||||
%% Tests.
|
%% 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) ->
|
v1_proxy_header(Config) ->
|
||||||
doc("Confirm we can read the proxy header at the start of the connection."),
|
doc("Confirm we can read the proxy header at the start of the connection."),
|
||||||
ProxyInfo = #{
|
ProxyInfo = #{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue