Skip to content

Commit 14ca41d

Browse files
committed
Bind :host to IPv6 localhost
1 parent 0830dab commit 14ca41d

File tree

4 files changed

+51
-10
lines changed

4 files changed

+51
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## v0.1.9 (TBA)
22

33
- `:httpd` server adapter now parses remote ip to tuple format
4+
- `:httpd` server adapter now parses host from host header
5+
- Specifying `:host` now also binds the hostname to IPv6 loopback
46
- Added `:ipfamily` option to set IP address type to use
57

68
## v0.1.8 (2023-02-10)

lib/test_server.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ defmodule TestServer do
160160
Produces a URL for current test server.
161161
162162
## Options
163-
* `:host` - binary host value, it'll be added to inet for IP 127.0.0.1, defaults to `"localhost"`;
163+
* `:host` - binary host value, it'll be added to inet for IP `127.0.0.1` and `::1`, defaults to `"localhost"`;
164164
"""
165165
@spec url(binary(), keyword()) :: binary()
166166
def url(uri, opts) when is_binary(uri), do: url(fetch_instance!(), uri, opts)
@@ -237,6 +237,7 @@ defmodule TestServer do
237237
defp maybe_enable_host(host) do
238238
:inet_db.set_lookup([:file, :dns])
239239
:inet_db.add_host({127, 0, 0, 1}, [String.to_charlist(host)])
240+
:inet_db.add_host({0, 0, 0, 0, 0, 0, 0, 1}, [String.to_charlist(host)])
240241

241242
host
242243
end

lib/test_server/http_server/httpd.ex

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,20 @@ defmodule TestServer.HTTPServer.Httpd do
108108
end
109109

110110
defp host(data) do
111-
{:init_data, _, host, _} = httpd(data, :init_data)
111+
data
112+
|> httpd(:parsed_header)
113+
|> Enum.find(&elem(&1, 0) == 'host')
114+
|> Kernel.||({'host', ''})
115+
|> elem(1)
116+
|> to_string()
117+
|> :binary.split(":")
118+
|> case do
119+
[host, port] ->
120+
{Integer.parse(port), host}
112121

113-
host
122+
[host] ->
123+
{nil, host}
124+
end
114125
end
115126

116127
defp peer(data) do

test/test_server_test.exs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ defmodule TestServerTest do
4747

4848
assert %X509.Test.Suite{} = options[:x509_suite]
4949

50-
httpc_opts = fn cacerts ->
50+
http_opts = fn cacerts ->
5151
[
5252
ssl: [
5353
verify: :verify_peer,
@@ -65,10 +65,10 @@ defmodule TestServerTest do
6565
invalid_cacerts = X509.Test.Suite.new().cacerts
6666

6767
assert {:error, {:failed_connect, _}} =
68-
request(TestServer.url("/"), httpc_opts: httpc_opts.(invalid_cacerts))
68+
request(TestServer.url("/"), http_opts: http_opts.(invalid_cacerts))
6969

7070
assert :ok = TestServer.add("/")
71-
assert {:ok, _} = request(TestServer.url("/"), httpc_opts: httpc_opts.(valid_cacerts))
71+
assert {:ok, _} = request(TestServer.url("/"), http_opts: http_opts.(valid_cacerts))
7272
end
7373

7474
test "starts in IPv6-only mode`" do
@@ -165,7 +165,7 @@ defmodule TestServerTest do
165165
end
166166
end
167167

168-
test "invalid `:host`" do
168+
test "with invalid `:host`" do
169169
TestServer.start()
170170

171171
assert_raise RuntimeError, ~r/Invalid host, got: :invalid/, fn ->
@@ -181,6 +181,32 @@ defmodule TestServerTest do
181181
refute TestServer.url("/") == TestServer.url("/", host: "bad-host")
182182
end
183183

184+
test "with `:host`" do
185+
TestServer.start()
186+
187+
assert :ok = TestServer.add("/", to: fn conn ->
188+
assert conn.remote_ip == {127, 0, 0, 1}
189+
assert conn.host == "custom-host"
190+
191+
Plug.Conn.send_resp(conn, 200, "OK")
192+
end)
193+
194+
assert {:ok, _} = request(TestServer.url("/", host: "custom-host"))
195+
end
196+
197+
test "with `:host` in IPv6-only mode" do
198+
TestServer.start(ipfamily: :inet6, http_server: {TestServer.HTTPServer.Httpd, []})
199+
200+
assert :ok = TestServer.add("/", to: fn conn ->
201+
assert conn.remote_ip == {0, 0, 0, 0, 0, 65_535, 32_512, 1}
202+
assert conn.host == "custom-host"
203+
204+
Plug.Conn.send_resp(conn, 200, "OK")
205+
end)
206+
207+
assert {:ok, _} = request(TestServer.url("/", host: "custom-host"))
208+
end
209+
184210
test "with multiple instances" do
185211
{:ok, instance_1} = TestServer.start()
186212
{:ok, instance_2} = TestServer.start()
@@ -691,13 +717,14 @@ defmodule TestServerTest do
691717

692718
def request(url, opts \\ []) do
693719
url = String.to_charlist(url)
694-
httpc_opts = Keyword.get(opts, :httpc_opts, [])
720+
httpc_http_opts = Keyword.get(opts, :http_opts, [])
721+
httpc_opts = Keyword.get(opts, :opts, [])
695722

696723
opts
697724
|> Keyword.get(:method, :get)
698725
|> case do
699-
:post -> :httpc.request(:post, {url, [], 'plain/text', 'OK'}, httpc_opts, [])
700-
:get -> :httpc.request(:get, {url, []}, httpc_opts, [])
726+
:post -> :httpc.request(:post, {url, [], 'plain/text', 'OK'}, httpc_http_opts, httpc_opts)
727+
:get -> :httpc.request(:get, {url, []}, httpc_http_opts, httpc_opts)
701728
end
702729
|> case do
703730
{:ok, {{_, 200, _}, _headers, body}} -> {:ok, to_string(body)}

0 commit comments

Comments
 (0)