aboutsummaryrefslogtreecommitdiffstats
path: root/test/rfc7231_SUITE.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-01-03 22:12:42 +0100
committerLoïc Hoguin <[email protected]>2019-01-03 22:12:42 +0100
commitfbe58ec837cc3c84b08d701c82b95222738c775f (patch)
treed0c34202fefe8c7aa8edf12128f03c360c320bc1 /test/rfc7231_SUITE.erl
parent8a30f96cf19f9104e3ae8df5f85df33b66b5bfc2 (diff)
downloadgun-fbe58ec837cc3c84b08d701c82b95222738c775f.tar.gz
gun-fbe58ec837cc3c84b08d701c82b95222738c775f.tar.bz2
gun-fbe58ec837cc3c84b08d701c82b95222738c775f.zip
Consolidate origin server test helpers
Also fixes an issue with switch_transport introduced when converting the Gun process to gen_statem.
Diffstat (limited to 'test/rfc7231_SUITE.erl')
-rw-r--r--test/rfc7231_SUITE.erl146
1 files changed, 37 insertions, 109 deletions
diff --git a/test/rfc7231_SUITE.erl b/test/rfc7231_SUITE.erl
index 5f7bd6f..9a112a8 100644
--- a/test/rfc7231_SUITE.erl
+++ b/test/rfc7231_SUITE.erl
@@ -16,11 +16,11 @@
-compile(export_all).
-compile(nowarn_export_all).
--ifdef(OTP_RELEASE).
--compile({nowarn_deprecated_function, [{ssl, ssl_accept, 2}]}).
--endif.
-
-import(ct_helper, [doc/1]).
+-import(gun_test, [init_origin/1]).
+-import(gun_test, [init_origin/2]).
+-import(gun_test, [receive_from/1]).
+-import(gun_test, [receive_from/2]).
all() ->
ct_helper:all(?MODULE).
@@ -39,7 +39,7 @@ do_proxy_start(Status, ConnectRespHeaders) ->
do_proxy_start(Status, ConnectRespHeaders, Delay) ->
Self = self(),
Pid = spawn_link(fun() -> do_proxy_init(Self, Status, ConnectRespHeaders, Delay) end),
- Port = do_receive(Pid),
+ Port = receive_from(Pid),
{ok, Pid, Port}.
do_proxy_init(Parent, Status, ConnectRespHeaders, Delay) ->
@@ -91,71 +91,6 @@ do_proxy_loop(ClientSocket, OriginSocket) ->
error(Msg)
end.
-do_origin_start(Transport) ->
- do_origin_start(Transport, http).
-
-do_origin_start(Transport, Protocol) ->
- Self = self(),
- Pid = spawn_link(fun() ->
- case Transport of
- tcp ->
- do_origin_init_tcp(Self);
- tls when Protocol =:= http ->
- do_origin_init_tls(Self);
- tls when Protocol =:= http2 ->
- do_origin_init_tls_h2(Self)
- end
- end),
- Port = do_receive(Pid),
- {ok, Pid, Port}.
-
-do_origin_init_tcp(Parent) ->
- {ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]),
- {ok, {_, Port}} = inet:sockname(ListenSocket),
- Parent ! {self(), Port},
- {ok, ClientSocket} = gen_tcp:accept(ListenSocket, 5000),
- do_origin_loop(Parent, ClientSocket, gen_tcp).
-
-do_origin_init_tls(Parent) ->
- Opts = ct_helper:get_certs_from_ets(),
- {ok, ListenSocket} = ssl:listen(0, [binary, {active, false}|Opts]),
- {ok, {_, Port}} = ssl:sockname(ListenSocket),
- Parent ! {self(), Port},
- {ok, ClientSocket} = ssl:transport_accept(ListenSocket, 5000),
- ok = ssl:ssl_accept(ClientSocket, 5000),
- do_origin_loop(Parent, ClientSocket, ssl).
-
-do_origin_init_tls_h2(Parent) ->
- Opts = ct_helper:get_certs_from_ets(),
- {ok, ListenSocket} = ssl:listen(0, [binary, {active, false},
- {alpn_preferred_protocols, [<<"h2">>]}|Opts]),
- {ok, {_, Port}} = ssl:sockname(ListenSocket),
- Parent ! {self(), Port},
- {ok, ClientSocket} = ssl:transport_accept(ListenSocket, 5000),
- ok = ssl:ssl_accept(ClientSocket, 5000),
- {ok, <<"h2">>} = ssl:negotiated_protocol(ClientSocket),
- do_origin_loop(Parent, ClientSocket, ssl).
-
-do_origin_loop(Parent, ClientSocket, ClientTransport) ->
- case ClientTransport:recv(ClientSocket, 0, 1000) of
- {ok, Data} ->
- Parent ! {self(), Data},
- do_origin_loop(Parent, ClientSocket, ClientTransport);
- {error, closed} ->
- ok
- end.
-
-do_receive(Pid) ->
- do_receive(Pid, 1000).
-
-do_receive(Pid, Timeout) ->
- receive
- {Pid, Msg} ->
- Msg
- after Timeout ->
- error(timeout)
- end.
-
%% Tests.
connect_http(_) ->
@@ -169,7 +104,7 @@ connect_https(_) ->
do_connect_http(tls).
do_connect_http(Transport) ->
- {ok, OriginPid, OriginPort} = do_origin_start(Transport, http),
+ {ok, OriginPid, OriginPort} = init_origin(Transport, http),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -179,10 +114,10 @@ do_connect_http(Transport) ->
port => OriginPort,
transport => Transport
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, 200, _} = gun:await(ConnPid, StreamRef),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
#{
@@ -210,7 +145,7 @@ connect_h2(_) ->
do_connect_h2(tls).
do_connect_h2(Transport) ->
- {ok, OriginPid, OriginPort} = do_origin_start(Transport, http2),
+ {ok, OriginPid, OriginPort} = init_origin(Transport, http2),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -221,18 +156,11 @@ do_connect_h2(Transport) ->
transport => Transport,
protocols => [http2]
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, 200, _} = gun:await(ConnPid, StreamRef),
+ timer:sleep(100), %% Give enough time for the handshake to fully complete.
_ = gun:get(ConnPid, "/proxied"),
- <<"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n",
- Len:24, 4:8, 0:40, %% SETTINGS
- Rest/bits>> = do_receive(OriginPid),
- _ = case Rest of
- <<_:Len/binary>> ->
- <<_:24, 1:8, _/bits>> = do_receive(OriginPid);
- <<_:Len/binary, _:24, 1:8, _/bits>> ->
- ok
- end,
+ <<_:24, 1:8, _/bits>> = receive_from(OriginPid),
#{
transport := Transport,
protocol := http2,
@@ -251,7 +179,7 @@ connect_through_multiple_proxies(_) ->
doc("CONNECT can be used to establish a TCP connection "
"to an HTTP/1.1 server via a tunnel going through "
"two separate HTTP proxies. (RFC7231 4.3.6)"),
- {ok, OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
{ok, Proxy1Pid, Proxy1Port} = do_proxy_start(),
{ok, Proxy2Pid, Proxy2Port} = do_proxy_start(),
{ok, ConnPid} = gun:open("localhost", Proxy1Port),
@@ -261,17 +189,17 @@ connect_through_multiple_proxies(_) ->
host => "localhost",
port => Proxy2Port
}),
- {request, <<"CONNECT">>, Authority1, 'HTTP/1.1', _} = do_receive(Proxy1Pid),
+ {request, <<"CONNECT">>, Authority1, 'HTTP/1.1', _} = receive_from(Proxy1Pid),
{response, fin, 200, _} = gun:await(ConnPid, StreamRef1),
Authority2 = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
StreamRef2 = gun:connect(ConnPid, #{
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority2, 'HTTP/1.1', _} = do_receive(Proxy2Pid),
+ {request, <<"CONNECT">>, Authority2, 'HTTP/1.1', _} = receive_from(Proxy2Pid),
{response, fin, 200, _} = gun:await(ConnPid, StreamRef2),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority2/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
#{
@@ -296,7 +224,7 @@ connect_through_multiple_proxies(_) ->
connect_delay(_) ->
doc("The CONNECT response may not be immediate."),
- {ok, OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(201, [], 2000),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort,
@@ -306,10 +234,10 @@ connect_delay(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid, 3000),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid, 3000),
{response, fin, 201, _} = gun:await(ConnPid, StreamRef),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
#{
@@ -329,7 +257,7 @@ connect_delay(_) ->
connect_response_201(_) ->
doc("2xx responses to CONNECT requests indicate "
"the tunnel was set up successfully. (RFC7231 4.3.6)"),
- {ok, OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(201),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -338,10 +266,10 @@ connect_response_201(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, 201, _} = gun:await(ConnPid, StreamRef),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
#{
@@ -384,7 +312,7 @@ do_connect_failure(Status) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, Status, Headers} = gun:await(ConnPid, StreamRef),
FailedStreamRef = gun:get(ConnPid, "/proxied"),
{response, fin, 501, _} = gun:await(ConnPid, FailedStreamRef),
@@ -399,7 +327,7 @@ do_connect_failure(Status) ->
connect_authority_form(_) ->
doc("CONNECT requests must use the authority-form. (RFC7231 4.3.6)"),
- {ok, _OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, _OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -408,13 +336,13 @@ connect_authority_form(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{<<"localhost">>, OriginPort} = cow_http_hd:parse_host(Authority),
gun:close(ConnPid).
connect_proxy_authorization(_) ->
doc("CONNECT requests may include a proxy-authorization header. (RFC7231 4.3.6)"),
- {ok, _OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, _OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -425,7 +353,7 @@ connect_proxy_authorization(_) ->
username => "essen",
password => "myrealpasswordis"
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = receive_from(ProxyPid),
{_, ProxyAuthorization} = lists:keyfind(<<"proxy-authorization">>, 1, Headers),
{basic, <<"essen">>, <<"myrealpasswordis">>}
= cow_http_hd:parse_proxy_authorization(ProxyAuthorization),
@@ -434,7 +362,7 @@ connect_proxy_authorization(_) ->
connect_request_no_transfer_encoding(_) ->
doc("The payload for CONNECT requests has no defined semantics. "
"The transfer-encoding header should not be sent. (RFC7231 4.3.6)"),
- {ok, _OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, _OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -443,14 +371,14 @@ connect_request_no_transfer_encoding(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = receive_from(ProxyPid),
false = lists:keyfind(<<"transfer-encoding">>, 1, Headers),
gun:close(ConnPid).
connect_request_no_content_length(_) ->
doc("The payload for CONNECT requests has no defined semantics. "
"The content-length header should not be sent. (RFC7231 4.3.6)"),
- {ok, _OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, _OriginPid, OriginPort} = init_origin(tcp),
{ok, ProxyPid, ProxyPort} = do_proxy_start(),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
{ok, ConnPid} = gun:open("localhost", ProxyPort),
@@ -459,14 +387,14 @@ connect_request_no_content_length(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', Headers} = receive_from(ProxyPid),
false = lists:keyfind(<<"content-length">>, 1, Headers),
gun:close(ConnPid).
connect_response_ignore_transfer_encoding(_) ->
doc("Clients must ignore transfer-encoding headers in responses "
"to CONNECT requests. (RFC7231 4.3.6)"),
- {ok, OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
Headers = [{<<"transfer-encoding">>, <<"chunked">>}],
{ok, ProxyPid, ProxyPort} = do_proxy_start(200, Headers),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
@@ -476,10 +404,10 @@ connect_response_ignore_transfer_encoding(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, 200, Headers} = gun:await(ConnPid, StreamRef),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
gun:close(ConnPid).
@@ -487,7 +415,7 @@ connect_response_ignore_transfer_encoding(_) ->
connect_response_ignore_content_length(_) ->
doc("Clients must ignore content-length headers in responses "
"to CONNECT requests. (RFC7231 4.3.6)"),
- {ok, OriginPid, OriginPort} = do_origin_start(tcp),
+ {ok, OriginPid, OriginPort} = init_origin(tcp),
Headers = [{<<"content-length">>, <<"1000">>}],
{ok, ProxyPid, ProxyPort} = do_proxy_start(200, Headers),
Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]),
@@ -497,10 +425,10 @@ connect_response_ignore_content_length(_) ->
host => "localhost",
port => OriginPort
}),
- {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = do_receive(ProxyPid),
+ {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid),
{response, fin, 200, Headers} = gun:await(ConnPid, StreamRef),
_ = gun:get(ConnPid, "/proxied"),
- Data = do_receive(OriginPid),
+ Data = receive_from(OriginPid),
Lines = binary:split(Data, <<"\r\n">>, [global]),
[<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines],
gun:close(ConnPid).