aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gun.erl14
-rw-r--r--test/gun_SUITE.erl10
-rw-r--r--test/ws_SUITE.erl42
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, _) ->