Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ All public functions in `TestServer` have been moved to `TestServer.HTTP`. The
HTTP server adapters in `TestServer.HTTPServer.*` have been moved to
`TestServer.HTTP.Server.*`.

TestServer now has SSH support with `TestServer.SSH`.

- Fixed bug where `:match` functions that raised errors always matched in `TestServer.HTTP.add/2` and `TestServer.HTTP.websocket_handle/3`
- Fixed UTF-8 response body handling for `TestServer.HTTP.Server.Httpd`
- Fixed invalid host header port parsing in `TestServer.HTTP.Server.Httpd`
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ Features:
- HTTP/1
- HTTP/2
- WebSocket
- SSH
- Built-in TLS with self-signed certificates
- Plug route matching

## Protocols

- [`TestServer.HTTP`](lib/test_server/http/README.md) - HTTP/1, HTTP/2, and WebSocket.
- [`TestServer.SSH`](lib/test_server/ssh/README.md) - SSH exec and shell.

<!-- MDOC !-->

Expand Down
41 changes: 41 additions & 0 deletions lib/test_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@ defmodule TestServer do
end
end

@doc false
def open_port(options) do
{port, options} =
case Keyword.get(options, :port, 0) do
{port, options} -> {port, options}
port -> {port, []}
end

unless is_integer(port) and port >= 0 and port <= 65_535,
do: raise("Invalid port, got: #{inspect(port)}")

with {:ok, socket} <- :gen_tcp.listen(port, options),
{:ok, port} <- :inet.port(socket),
true <- :erlang.port_close(socket) do
port
else
{:error, error} ->
raise("Could not listen to port #{inspect(port)}, because: #{inspect(error)}")
end
end

@doc false
def fetch_instance!(protocol_module) do
instance_module = Module.concat(protocol_module, Instance)
Expand All @@ -112,4 +133,24 @@ defmodule TestServer do
{:ok, instance} -> instance
end
end

@doc false
def get_host(options) do
host = Keyword.get(options, :host)

unless is_nil(host) or is_binary(host),
do: raise("Invalid host, got: #{inspect(host)}")

case host do
nil ->
"localhost"

host ->
:inet_db.set_lookup([:file, :dns])
:inet_db.add_host({127, 0, 0, 1}, [String.to_charlist(host)])
:inet_db.add_host({0, 0, 0, 0, 0, 0, 0, 1}, [String.to_charlist(host)])

host
end
end
end
15 changes: 1 addition & 14 deletions lib/test_server/http.ex
Original file line number Diff line number Diff line change
Expand Up @@ -171,25 +171,12 @@ defmodule TestServer.HTTP do
def url(instance, uri, options) do
TestServer.ensure_instance_alive!(__MODULE__, instance)

unless is_nil(options[:host]) or is_binary(options[:host]),
do: raise("Invalid host, got: #{inspect(options[:host])}")

domain = maybe_enable_host(options[:host])
domain = TestServer.get_host(options)
options = Instance.get_options(instance)

"#{Keyword.fetch!(options, :scheme)}://#{domain}:#{Keyword.fetch!(options, :port)}#{uri}"
end

defp maybe_enable_host(nil), do: "localhost"

defp maybe_enable_host(host) do
:inet_db.set_lookup([:file, :dns])
:inet_db.add_host({127, 0, 0, 1}, [String.to_charlist(host)])
:inet_db.add_host({0, 0, 0, 0, 0, 0, 0, 1}, [String.to_charlist(host)])

host
end

@spec add(binary()) :: :ok
def add(uri), do: add(uri, [])

Expand Down
22 changes: 1 addition & 21 deletions lib/test_server/http/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ defmodule TestServer.HTTP.Server do
@doc false
@spec start(pid(), keyword()) :: {:ok, keyword()} | {:error, any()}
def start(instance, options) do
port = open_port(options)
port = TestServer.open_port(options)
scheme = parse_scheme(options)
{tls_options, x509_options} = maybe_generate_x509_suite(options, scheme)
ip_family = Keyword.get(options, :ipfamily, :inet)
Expand All @@ -65,26 +65,6 @@ defmodule TestServer.HTTP.Server do
end
end

defp open_port(options) do
{port, options} =
case Keyword.get(options, :port, 0) do
{port, options} -> {port, options}
port -> {port, []}
end

unless is_integer(port) and port >= 0 and port <= 65_535,
do: raise("Invalid port, got: #{inspect(port)}")

with {:ok, socket} <- :gen_tcp.listen(port, options),
{:ok, port} <- :inet.port(socket),
true <- :erlang.port_close(socket) do
port
else
{:error, error} ->
raise("Could not listen to port #{inspect(port)}, because: #{inspect(error)}")
end
end

defp parse_scheme(options) do
scheme = Keyword.get(options, :scheme, :http)

Expand Down
Loading
Loading