diff options
-rw-r--r-- | src/gun.erl | 14 | ||||
-rw-r--r-- | test/gun_SUITE.erl | 10 | ||||
-rw-r--r-- | test/ws_SUITE.erl | 42 |
3 files changed, 60 insertions, 6 deletions
diff --git a/src/gun.erl b/src/gun.erl index 8fb326d..085e47f 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -1016,6 +1016,18 @@ start_link(Owner, Host, Port, Opts) -> init({Owner, Host, Port, Opts}) -> Retry = maps:get(retry, Opts, 5), OriginTransport = maps:get(transport, Opts, default_transport(Port)), + %% When Unix Domain Sockets are used we set + %% the origin authority to "localhost" by default. + {OriginHost, OriginPort} = case Host of + {local, _} -> + OriginPort0 = case OriginTransport of + tcp -> 80; + _ -> 443 + end, + {<<"localhost">>, OriginPort0}; + _ -> + {Host, Port} + end, %% The OriginScheme is not really http when we connect to socks/raw. %% This is corrected in the gun:info/1 and gun:stream_info/2 functions where applicable. {OriginScheme, Transport} = case OriginTransport of @@ -1037,7 +1049,7 @@ init({Owner, Host, Port, Opts}) -> CookieStore = maps:get(cookie_store, Opts, undefined), State = #state{owner=Owner, status={up, OwnerRef}, host=Host, port=Port, origin_scheme=OriginScheme, - origin_host=Host, origin_port=Port, opts=Opts, + origin_host=OriginHost, origin_port=OriginPort, opts=Opts, transport=Transport, messages=Transport:messages(), event_handler=EvHandler, event_handler_state=EvHandlerState, cookie_store=CookieStore}, diff --git a/test/gun_SUITE.erl b/test/gun_SUITE.erl index 9644ace..1c9ba23 100644 --- a/test/gun_SUITE.erl +++ b/test/gun_SUITE.erl @@ -759,11 +759,13 @@ do_unix_socket_connect() -> ok = gen_tcp:close(LSock) end, spawn(Acceptor), - {ok, Pid} = gun:open_unix(SocketPath, #{}), - _ = gun:get(Pid, "/", [{<<"host">>, <<"localhost">>}]), + {ok, ConnPid} = gun:open_unix(SocketPath, #{}), + #{origin_host := <<"localhost">>} = gun:info(ConnPid), + _ = gun:get(ConnPid, "/"), receive - {recv, _} -> - gun:close(Pid) + {recv, Recv} -> + {_, _} = binary:match(Recv, <<"\r\nhost: localhost\r\n">>), + gun:close(ConnPid) end. uppercase_header_name(_) -> diff --git a/test/ws_SUITE.erl b/test/ws_SUITE.erl index 4f0a2cf..8900fee 100644 --- a/test/ws_SUITE.erl +++ b/test/ws_SUITE.erl @@ -30,7 +30,8 @@ groups() -> http10_upgrade_error, http11_request_error, http11_keepalive, - http11_keepalive_default_silence_pings + http11_keepalive_default_silence_pings, + unix_socket_hostname ], [ {http, [], Tests}, @@ -259,6 +260,45 @@ subprotocol_required_but_missing(Config) -> {ok, <<"undefined">>} = gun:await_body(ConnPid, StreamRef), gun:close(ConnPid). +unix_socket_hostname(_) -> + case os:type() of + {win32, _} -> + {skip, "Unix Domain Sockets are not available on Windows."}; + _ -> + do_unix_socket_hostname() + end. + +do_unix_socket_hostname() -> + doc("Ensure that the hostname used for Websocket upgrades " + "on Unix Domain Sockets is 'localhost' by default."), + DataDir = "/tmp/gun", + SocketPath = filename:join(DataDir, "gun.sock"), + ok = filelib:ensure_dir(SocketPath), + _ = file:delete(SocketPath), + TCPOpts = [ + {ifaddr, {local, SocketPath}}, + binary, {nodelay, true}, {active, false}, + {packet, raw}, {reuseaddr, true} + ], + {ok, LSock} = gen_tcp:listen(0, TCPOpts), + Tester = self(), + Acceptor = fun() -> + {ok, S} = gen_tcp:accept(LSock), + {ok, R} = gen_tcp:recv(S, 0), + Tester ! {recv, R}, + ok = gen_tcp:close(S), + ok = gen_tcp:close(LSock) + end, + spawn(Acceptor), + {ok, ConnPid} = gun:open_unix(SocketPath, #{}), + #{origin_host := <<"localhost">>} = gun:info(ConnPid), + _ = gun:ws_upgrade(ConnPid, "/", []), + receive + {recv, Recv} -> + {_, _} = binary:match(Recv, <<"\r\nhost: localhost\r\n">>), + gun:close(ConnPid) + end. + %% Internal. do_await_enable_connect_protocol(http, _) -> |