From 02dd576a837b8b47b1c656c6f4b8769c1aeb4ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Thu, 19 Sep 2019 15:14:31 +0200 Subject: Add Socks5->HTTP/2 tests Also consolidate the ALPN code in the tls_handshake state rather than doing it in CONNECT/Socks separately. Also improves the origin tests by sending a message once the handshake is completed instead of having timeouts. --- src/gun.erl | 28 +++++++++--------- test/gun_SUITE.erl | 12 ++++++-- test/gun_test.erl | 2 ++ test/rfc7230_SUITE.erl | 1 + test/rfc7231_SUITE.erl | 8 +++++- test/rfc7540_SUITE.erl | 10 +++---- test/shutdown_SUITE.erl | 9 +++--- test/socks_SUITE.erl | 75 +++++++++++++++++++++++++++++++++++++------------ 8 files changed, 100 insertions(+), 45 deletions(-) diff --git a/src/gun.erl b/src/gun.erl index a6c1edc..3802ee0 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -962,10 +962,14 @@ tls_handshake(internal, {tls_handshake, HandshakeEvent, Protocols}, end; %% TLS over TLS. tls_handshake(internal, {tls_handshake, - HandshakeEvent0=#{tls_opts := TLSOpts, timeout := TLSTimeout}, Protocols}, + HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols}, State=#state{socket=Socket, transport=gun_tls, origin_host=OriginHost, origin_port=OriginPort, event_handler=EvHandler, event_handler_state=EvHandlerState0}) -> - HandshakeEvent = HandshakeEvent0#{socket => Socket}, + TLSOpts = ensure_alpn(Protocols, TLSOpts0), + HandshakeEvent = HandshakeEvent0#{ + tls_opts => TLSOpts, + socket => Socket + }, EvHandlerState = EvHandler:tls_handshake_start(HandshakeEvent, EvHandlerState0), {ok, ProxyPid} = gun_tls_proxy:start_link(OriginHost, OriginPort, TLSOpts, TLSTimeout, Socket, gun_tls, {HandshakeEvent, Protocols}), @@ -1003,8 +1007,12 @@ tls_handshake(Type, Event, State) -> handle_common_connected(Type, Event, ?FUNCTION_NAME, State). normal_tls_handshake(Socket, State=#state{event_handler=EvHandler, event_handler_state=EvHandlerState0}, - HandshakeEvent0=#{tls_opts := TLSOpts, timeout := TLSTimeout}, Protocols) -> - HandshakeEvent = HandshakeEvent0#{socket => Socket}, + HandshakeEvent0=#{tls_opts := TLSOpts0, timeout := TLSTimeout}, Protocols) -> + TLSOpts = ensure_alpn(Protocols, TLSOpts0), + HandshakeEvent = HandshakeEvent0#{ + tls_opts => TLSOpts, + socket => Socket + }, EvHandlerState1 = EvHandler:tls_handshake_start(HandshakeEvent, EvHandlerState0), case gun_tls:connect(Socket, TLSOpts, TLSTimeout) of {ok, TLSSocket} -> @@ -1068,7 +1076,7 @@ connected(cast, {connect, ReplyTo, StreamRef, Destination0, Headers, InitialFlow State=#state{protocol=Protocol, protocol_state=ProtoState}) -> %% The protocol option has been deprecated in favor of the protocols option. %% Nobody probably ended up using it, but let's not break the interface. - Destination1 = case Destination0 of + Destination = case Destination0 of #{protocols := _} -> Destination0; #{protocol := DestProto} -> @@ -1076,14 +1084,6 @@ connected(cast, {connect, ReplyTo, StreamRef, Destination0, Headers, InitialFlow _ -> Destination0 end, - Destination = case Destination1 of - #{transport := tls} -> - Destination1#{tls_opts => ensure_alpn( - maps:get(protocols, Destination1, [http]), - maps:get(tls_opts, Destination1, []))}; - _ -> - Destination1 - end, ProtoState2 = Protocol:connect(ProtoState, StreamRef, ReplyTo, Destination, Headers, InitialFlow), {keep_state, State#state{protocol_state=ProtoState2}}; %% Public Websocket interface. @@ -1326,7 +1326,7 @@ commands([TLSHandshake={tls_handshake, _, _}], State) -> {next_event, internal, TLSHandshake}}; %% Switch from not_fully_connected to connected. commands([{mode, http}], State) -> - {next_state, connected, State}. + {next_state, connected, active(State)}. disconnect(State0=#state{owner=Owner, status=Status, opts=Opts, socket=Socket, transport=Transport, diff --git a/test/gun_SUITE.erl b/test/gun_SUITE.erl index 0beee43..a0ecddd 100644 --- a/test/gun_SUITE.erl +++ b/test/gun_SUITE.erl @@ -42,6 +42,7 @@ atom_header_name(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open("localhost", OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), _ = gun:get(Pid, "/", [ {'User-Agent', "Gun/atom-headers"} ]), @@ -55,6 +56,7 @@ atom_hostname(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open('localhost', OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), _ = gun:get(Pid, "/"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -95,6 +97,7 @@ ignore_empty_data_http(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open("localhost", OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), Ref = gun:put(Pid, "/", []), gun:data(Pid, Ref, nofin, "hello "), gun:data(Pid, Ref, nofin, ["", <<>>]), @@ -110,7 +113,7 @@ ignore_empty_data_http2(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http2), {ok, Pid} = gun:open("localhost", OriginPort, #{protocols => [http2]}), {ok, http2} = gun:await_up(Pid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), Ref = gun:put(Pid, "/", []), gun:data(Pid, Ref, nofin, "hello "), gun:data(Pid, Ref, nofin, ["", <<>>]), @@ -180,6 +183,7 @@ list_header_name(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open("localhost", OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), _ = gun:get(Pid, "/", [ {"User-Agent", "Gun/list-headers"} ]), @@ -193,6 +197,7 @@ map_headers(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open("localhost", OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), _ = gun:get(Pid, "/", #{ <<"USER-agent">> => "Gun/map-headers" }), @@ -434,13 +439,13 @@ stream_info_http(_) -> stream_info_http2(_) -> doc("Ensure the function gun:stream_info/2 works as expected for HTTP/2."), - {ok, _, OriginPort} = init_origin(tcp, http2, + {ok, OriginPid, OriginPort} = init_origin(tcp, http2, fun(_, _, _) -> timer:sleep(200) end), {ok, Pid} = gun:open("localhost", OriginPort, #{ protocols => [http2] }), {ok, http2} = gun:await_up(Pid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), {ok, undefined} = gun:stream_info(Pid, make_ref()), StreamRef = gun:get(Pid, "/"), Self = self(), @@ -535,6 +540,7 @@ uppercase_header_name(_) -> {ok, OriginPid, OriginPort} = init_origin(tcp, http), {ok, Pid} = gun:open("localhost", OriginPort), {ok, http} = gun:await_up(Pid), + handshake_completed = receive_from(OriginPid), _ = gun:get(Pid, "/", [ {<<"USER-agent">>, "Gun/uppercase-headers"} ]), diff --git a/test/gun_test.erl b/test/gun_test.erl index a2cbf6d..a263335 100644 --- a/test/gun_test.erl +++ b/test/gun_test.erl @@ -49,6 +49,7 @@ init_origin(Parent, tcp, Protocol, Fun) -> http2 -> http2_handshake(ClientSocket, gen_tcp); _ -> ok end, + Parent ! {self(), handshake_completed}, Fun(Parent, ClientSocket, gen_tcp); init_origin(Parent, tls, Protocol, Fun) -> Opts0 = ct_helper:get_certs_from_ets(), @@ -68,6 +69,7 @@ init_origin(Parent, tls, Protocol, Fun) -> _ -> ok end, + Parent ! {self(), handshake_completed}, Fun(Parent, ClientSocket, ssl). http2_handshake(Socket, Transport) -> diff --git a/test/rfc7230_SUITE.erl b/test/rfc7230_SUITE.erl index e090545..da7b426 100644 --- a/test/rfc7230_SUITE.erl +++ b/test/rfc7230_SUITE.erl @@ -52,6 +52,7 @@ do_host_port(Transport, DefaultPort, HostHeaderPort) -> end, 5000), %% Confirm the default port is not sent in the request. _ = gun:get(ConnPid, "/"), + handshake_completed = receive_from(OriginPid), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), [<<"host: localhost", Rest/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines], diff --git a/test/rfc7231_SUITE.erl b/test/rfc7231_SUITE.erl index e5df4ef..ec63cbe 100644 --- a/test/rfc7231_SUITE.erl +++ b/test/rfc7231_SUITE.erl @@ -168,6 +168,7 @@ do_connect_http(OriginScheme, OriginTransport, ProxyTransport) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid), {response, fin, 200, _} = gun:await(ConnPid, StreamRef), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -221,7 +222,7 @@ do_connect_h2(OriginScheme, OriginTransport, ProxyTransport) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid), {response, fin, 200, _} = gun:await(ConnPid, StreamRef), - timer:sleep(1000), %% Give enough time for the ssl/h2 handshakes to fully complete. + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), <<_:24, 1:8, _/bits>> = receive_from(OriginPid), #{ @@ -262,6 +263,7 @@ connect_through_multiple_proxies(_) -> }), {request, <<"CONNECT">>, Authority2, 'HTTP/1.1', _} = receive_from(Proxy2Pid), {response, fin, 200, _} = gun:await(ConnPid, StreamRef2), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -301,6 +303,7 @@ connect_delay(_) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid, 3000), {response, fin, 201, _} = gun:await(ConnPid, StreamRef), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -334,6 +337,7 @@ connect_response_201(_) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid), {response, fin, 201, _} = gun:await(ConnPid, StreamRef), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -474,6 +478,7 @@ connect_response_ignore_transfer_encoding(_) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid), {response, fin, 200, Headers} = gun:await(ConnPid, StreamRef), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), @@ -495,6 +500,7 @@ connect_response_ignore_content_length(_) -> }), {request, <<"CONNECT">>, Authority, 'HTTP/1.1', _} = receive_from(ProxyPid), {response, fin, 200, Headers} = gun:await(ConnPid, StreamRef), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), Data = receive_from(OriginPid), Lines = binary:split(Data, <<"\r\n">>, [global]), diff --git a/test/rfc7540_SUITE.erl b/test/rfc7540_SUITE.erl index 14e9c0c..6f08ce3 100644 --- a/test/rfc7540_SUITE.erl +++ b/test/rfc7540_SUITE.erl @@ -58,12 +58,12 @@ do_authority_port(Transport0, DefaultPort, AuthorityHeaderPort) -> protocols => [http2] }), {ok, http2} = gun:await_up(ConnPid), + handshake_completed = receive_from(OriginPid), %% Change the origin's port in the state to trigger the default port behavior. _ = sys:replace_state(ConnPid, fun({StateName, StateData}) -> {StateName, setelement(8, StateData, DefaultPort)} end, 5000), %% Confirm the default port is not sent in the request. - timer:sleep(100), %% Give enough time for the handshake to fully complete. _ = gun:get(ConnPid, "/"), ReqHeaders = receive_from(OriginPid), {_, <<"localhost", Rest/bits>>} = lists:keyfind(<<":authority">>, 1, ReqHeaders), @@ -73,7 +73,7 @@ do_authority_port(Transport0, DefaultPort, AuthorityHeaderPort) -> lingering_data_counts_toward_connection_window(_) -> doc("DATA frames received after sending RST_STREAM must be counted " "toward the connection flow-control window. (RFC7540 5.1)"), - {ok, _, Port} = init_origin(tcp, http2, fun(_, Socket, Transport) -> + {ok, OriginPid, Port} = init_origin(tcp, http2, fun(_, Socket, Transport) -> %% Step 2. %% Receive a HEADERS frame. {ok, <>} = Transport:recv(Socket, 9, 1000), @@ -110,7 +110,7 @@ lingering_data_counts_toward_connection_window(_) -> } }), {ok, http2} = gun:await_up(ConnPid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), %% Step 1. StreamRef = gun:get(ConnPid, "/"), %% Step 4. @@ -124,7 +124,7 @@ lingering_data_counts_toward_connection_window(_) -> headers_priority_flag(_) -> doc("HEADERS frames may include a PRIORITY flag indicating " "that stream dependency information is attached. (RFC7540 6.2)"), - {ok, _, Port} = init_origin(tcp, http2, fun(_, Socket, Transport) -> + {ok, OriginPid, Port} = init_origin(tcp, http2, fun(_, Socket, Transport) -> %% Receive a HEADERS frame. {ok, <<_:24, 1:8, _:8, 1:32>>} = Transport:recv(Socket, 9, 1000), %% Send a HEADERS frame with PRIORITY back. @@ -151,7 +151,7 @@ headers_priority_flag(_) -> end), {ok, ConnPid} = gun:open("localhost", Port, #{protocols => [http2]}), {ok, http2} = gun:await_up(ConnPid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), StreamRef = gun:get(ConnPid, "/"), {response, fin, 200, _} = gun:await(ConnPid, StreamRef), gun:close(ConnPid). diff --git a/test/shutdown_SUITE.erl b/test/shutdown_SUITE.erl index d3a2f56..173fd50 100644 --- a/test/shutdown_SUITE.erl +++ b/test/shutdown_SUITE.erl @@ -19,6 +19,7 @@ -import(ct_helper, [doc/1]). -import(ct_helper, [config/2]). -import(gun_test, [init_origin/3]). +-import(gun_test, [receive_from/1]). all() -> [{group, shutdown}]. @@ -377,7 +378,7 @@ http2_server_goaway_one_stream(_) -> doc("HTTP/2: Confirm that the Gun process shuts down gracefully " "when receiving a GOAWAY frame with one active stream and " "retry is disabled."), - {ok, _, OriginPort} = init_origin(tcp, http2, fun(_, Socket, Transport) -> + {ok, OriginPid, OriginPort} = init_origin(tcp, http2, fun(_, Socket, Transport) -> %% Receive a HEADERS frame. {ok, <>} = Transport:recv(Socket, 9, 1000), %% Skip the header. @@ -401,7 +402,7 @@ http2_server_goaway_one_stream(_) -> retry => 0 }), {ok, Protocol} = gun:await_up(ConnPid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), StreamRef = gun:get(ConnPid, "/"), ConnRef = monitor(process, ConnPid), {response, fin, 200, _} = gun:await(ConnPid, StreamRef), @@ -411,7 +412,7 @@ http2_server_goaway_many_streams(_) -> doc("HTTP/2: Confirm that the Gun process shuts down gracefully " "when receiving a GOAWAY frame with many active streams and " "retry is disabled."), - {ok, _, OriginPort} = init_origin(tcp, http2, fun(_, Socket, Transport) -> + {ok, OriginPid, OriginPort} = init_origin(tcp, http2, fun(_, Socket, Transport) -> %% Stream 1. %% Receive a HEADERS frame. {ok, <>} = Transport:recv(Socket, 9, 1000), @@ -458,7 +459,7 @@ http2_server_goaway_many_streams(_) -> retry => 0 }), {ok, Protocol} = gun:await_up(ConnPid), - timer:sleep(100), %% Give enough time for the handshake to fully complete. + handshake_completed = receive_from(OriginPid), StreamRef1 = gun:get(ConnPid, "/"), StreamRef2 = gun:get(ConnPid, "/"), StreamRef3 = gun:get(ConnPid, "/"), diff --git a/test/socks_SUITE.erl b/test/socks_SUITE.erl index 81d4c10..9d80328 100644 --- a/test/socks_SUITE.erl +++ b/test/socks_SUITE.erl @@ -146,38 +146,70 @@ do_auth_method({username_password, _, _}) -> username_password. socks5_tcp_http_none(_) -> doc("Use Socks5 over TCP and without authentication to connect to an HTTP server."), - do_socks5_http(<<"http">>, tcp, tcp, none). + do_socks5(<<"http">>, tcp, http, tcp, none). socks5_tcp_http_username_password(_) -> doc("Use Socks5 over TCP and without authentication to connect to an HTTP server."), - do_socks5_http(<<"http">>, tcp, tcp, {username_password, <<"user">>, <<"password">>}). + do_socks5(<<"http">>, tcp, http, tcp, {username_password, <<"user">>, <<"password">>}). socks5_tcp_https_none(_) -> doc("Use Socks5 over TCP and without authentication to connect to an HTTPS server."), - do_socks5_http(<<"https">>, tls, tcp, none). + do_socks5(<<"https">>, tls, http, tcp, none). socks5_tcp_https_username_password(_) -> doc("Use Socks5 over TCP and without authentication to connect to an HTTPS server."), - do_socks5_http(<<"https">>, tls, tcp, {username_password, <<"user">>, <<"password">>}). + do_socks5(<<"https">>, tls, http, tcp, {username_password, <<"user">>, <<"password">>}). socks5_tls_http_none(_) -> doc("Use Socks5 over TLS and without authentication to connect to an HTTP server."), - do_socks5_http(<<"http">>, tcp, tls, none). + do_socks5(<<"http">>, tcp, http, tls, none). socks5_tls_http_username_password(_) -> doc("Use Socks5 over TLS and without authentication to connect to an HTTP server."), - do_socks5_http(<<"http">>, tcp, tls, {username_password, <<"user">>, <<"password">>}). + do_socks5(<<"http">>, tcp, http, tls, {username_password, <<"user">>, <<"password">>}). socks5_tls_https_none(_) -> - doc("Use Socks5 over TLS and without authentication to connect to an HTTP server."), - do_socks5_http(<<"https">>, tls, tls, none). + doc("Use Socks5 over TLS and without authentication to connect to an HTTPS server."), + do_socks5(<<"https">>, tls, http, tls, none). socks5_tls_https_username_password(_) -> - doc("Use Socks5 over TLS and without authentication to connect to an HTTP server."), - do_socks5_http(<<"https">>, tls, tls, {username_password, <<"user">>, <<"password">>}). + doc("Use Socks5 over TLS and without authentication to connect to an HTTPS server."), + do_socks5(<<"https">>, tls, http, tls, {username_password, <<"user">>, <<"password">>}). + +socks5_tcp_h2c_none(_) -> + doc("Use Socks5 over TCP and without authentication to connect to an HTTP/2 server over TCP."), + do_socks5(<<"http">>, tcp, http2, tcp, none). + +socks5_tcp_h2c_username_password(_) -> + doc("Use Socks5 over TCP and without authentication to connect to an HTTP/2 server over TCP."), + do_socks5(<<"http">>, tcp, http2, tcp, {username_password, <<"user">>, <<"password">>}). + +socks5_tcp_h2_none(_) -> + doc("Use Socks5 over TCP and without authentication to connect to an HTTP/2 server over TLS."), + do_socks5(<<"https">>, tls, http2, tcp, none). + +socks5_tcp_h2_username_password(_) -> + doc("Use Socks5 over TCP and without authentication to connect to an HTTP/2 server over TLS."), + do_socks5(<<"https">>, tls, http2, tcp, {username_password, <<"user">>, <<"password">>}). -do_socks5_http(OriginScheme, OriginTransport, ProxyTransport, SocksAuth) -> - {ok, OriginPid, OriginPort} = init_origin(OriginTransport, http), +socks5_tls_h2c_none(_) -> + doc("Use Socks5 over TLS and without authentication to connect to an HTTP/2 server over TCP."), + do_socks5(<<"http">>, tcp, http2, tls, none). + +socks5_tls_h2c_username_password(_) -> + doc("Use Socks5 over TLS and without authentication to connect to an HTTP/2 server over TCP."), + do_socks5(<<"http">>, tcp, http2, tls, {username_password, <<"user">>, <<"password">>}). + +socks5_tls_h2_none(_) -> + doc("Use Socks5 over TLS and without authentication to connect to an HTTP/2 server over TLS."), + do_socks5(<<"https">>, tls, http2, tls, none). + +socks5_tls_h2_username_password(_) -> + doc("Use Socks5 over TLS and without authentication to connect to an HTTP/2 server over TLS."), + do_socks5(<<"https">>, tls, http2, tls, {username_password, <<"user">>, <<"password">>}). + +do_socks5(OriginScheme, OriginTransport, OriginProtocol, ProxyTransport, SocksAuth) -> + {ok, OriginPid, OriginPort} = init_origin(OriginTransport, OriginProtocol), {ok, ProxyPid, ProxyPort} = do_proxy_start(ProxyTransport, SocksAuth), Authority = iolist_to_binary(["localhost:", integer_to_binary(OriginPort)]), {ok, ConnPid} = gun:open("localhost", ProxyPort, #{ @@ -186,12 +218,13 @@ do_socks5_http(OriginScheme, OriginTransport, ProxyTransport, SocksAuth) -> auth => [SocksAuth], host => "localhost", port => OriginPort, - transport => OriginTransport + transport => OriginTransport, + protocols => [OriginProtocol] }}] }), %% We receive a gun_up and a gun_socks_connected. {ok, socks} = gun:await_up(ConnPid), - {ok, http} = gun:await_up(ConnPid), + {ok, OriginProtocol} = gun:await_up(ConnPid), %% The proxy received two packets. AuthMethod = do_auth_method(SocksAuth), {auth_methods, 1, [AuthMethod]} = receive_from(ProxyPid), @@ -200,13 +233,19 @@ do_socks5_http(OriginScheme, OriginTransport, ProxyTransport, SocksAuth) -> username_password -> SocksAuth = receive_from(ProxyPid) end, {connect, <<"localhost">>, OriginPort} = receive_from(ProxyPid), + handshake_completed = receive_from(OriginPid), _ = gun:get(ConnPid, "/proxied"), - Data = receive_from(OriginPid), - Lines = binary:split(Data, <<"\r\n">>, [global]), - [<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines], + _ = case OriginProtocol of + http -> + Data = receive_from(OriginPid), + Lines = binary:split(Data, <<"\r\n">>, [global]), + [<<"host: ", Authority/bits>>] = [L || <<"host: ", _/bits>> = L <- Lines]; + http2 -> + <<_:24, 1:8, _/bits>> = receive_from(OriginPid) + end, #{ transport := OriginTransport, - protocol := http, + protocol := OriginProtocol, origin_scheme := OriginScheme, origin_host := "localhost", origin_port := OriginPort, -- cgit v1.2.3