From f328916937c67b3c9679e4f11d4594c39d36f85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Wed, 26 Sep 2018 12:08:11 +0200 Subject: Keep track of the intermediaries the connection go through Also augment the CONNECT tests to confirm that the intermediaries are accounted for. --- src/gun.erl | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) (limited to 'src/gun.erl') diff --git a/src/gun.erl b/src/gun.erl index 9c92281..daa5c62 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -128,6 +128,14 @@ }. -export_type([connect_destination/0]). +-type intermediary() :: #{ + type := connect, + host := inet:hostname() | inet:ip_address(), + port := inet:port_number(), + transport := tcp | tls, + protocol := http | http2 +}. + %% @todo When/if HTTP/2 CONNECT gets implemented, we will want an option here %% to indicate that the request must be sent on an existing CONNECT stream. %% This is of course not required for HTTP/1.1 since the CONNECT takes over @@ -163,6 +171,7 @@ port :: inet:port_number(), origin_host :: inet:hostname() | inet:ip_address(), origin_port :: inet:port_number(), + intermediaries = [] :: [intermediary()], opts :: opts(), keepalive_ref :: undefined | reference(), socket :: undefined | inet:socket() | ssl:sslsocket(), @@ -275,9 +284,25 @@ consider_tracing(_, _) -> -spec info(pid()) -> map(). info(ServerPid) -> - {_, #state{socket=Socket, transport=Transport}} = sys:get_state(ServerPid), + {_, #state{ + socket=Socket, + transport=Transport, + protocol=Protocol, + origin_host=OriginHost, + origin_port=OriginPort, + intermediaries=Intermediaries + }} = sys:get_state(ServerPid), {ok, {SockIP, SockPort}} = Transport:sockname(Socket), - #{sock_ip => SockIP, sock_port => SockPort}. + #{ + transport => Transport:name(), + protocol => Protocol:name(), + sock_ip => SockIP, + sock_port => SockPort, + origin_host => OriginHost, + origin_port => OriginPort, + %% Intermediaries are listed in the order data goes through them. + intermediaries => lists:reverse(Intermediaries) + }. -spec close(pid()) -> ok. close(ServerPid) -> @@ -866,8 +891,23 @@ commands([Error={error, _}|_], State=#state{socket=Socket, transport=Transport}) commands([{state, ProtoState}|Tail], State) -> commands(Tail, State#state{protocol_state=ProtoState}); %% @todo The scheme should probably not be ignored. -commands([{origin, _Scheme, Host, Port}|Tail], State) -> - commands(Tail, State#state{origin_host=Host, origin_port=Port}); +%% +%% Order is important: the origin must be changed before +%% the transport and/or protocol in order to keep track +%% of the intermediaries properly. +commands([{origin, _Scheme, Host, Port, Type}|Tail], + State=#state{transport=Transport, protocol=Protocol, + origin_host=IntermediateHost, origin_port=IntermediatePort, + intermediaries=Intermediaries}) -> + Info = #{ + type => Type, + host => IntermediateHost, + port => IntermediatePort, + transport => Transport:name(), + protocol => Protocol:name() + }, + commands(Tail, State#state{origin_host=Host, origin_port=Port, + intermediaries=[Info|Intermediaries]}); commands([{switch_transport, Transport, Socket}|Tail], State) -> commands(Tail, State#state{socket=Socket, transport=Transport}); %% @todo The two loops should be reunified and this clause generalized. -- cgit v1.2.3