Current section
Files
Jump to
Current section
Files
lib/main_proxy.ex
defmodule MainProxy do
@external_resource "README.md"
@moduledoc "README.md"
|> File.read!()
|> String.split("<!-- MDOC !-->")
|> Enum.fetch!(1)
require Logger
@doc false
def should_start_server?() do
# the server will be started in following situations:
# - enable `server: true` option for main_proxy (by default)
# - run `iex -S mix phx.server`
# - run `mix phx.server`
Application.get_env(:phoenix, :serve_endpoints, false) ||
Application.get_env(:main_proxy, :server, true)
end
# Builds the spec for each Plug.Cowboy process
@doc false
def spec(handler_opts, callback_module) do
Enum.reduce([:http, :https], [], fn scheme, result ->
case Application.get_env(:main_proxy, scheme) do
nil ->
# no config for this scheme, that's ok, just skip
result
scheme_opts ->
backends = Keyword.fetch!(handler_opts, :backends)
opts = build_opts(scheme, scheme_opts, handler_opts, callback_module)
Logger.info("[main_proxy] Listening on #{scheme} with options: #{inspect(opts)}")
[
{
Plug.Cowboy,
scheme: scheme, plug: {MainProxy.Plug, backends: backends}, options: opts
}
| result
]
end
end)
end
defp build_opts(scheme, scheme_opts, _handler_opts, callback_module) do
port = :proplists.get_value(:port, scheme_opts)
opts =
callback_module.merge_config(scheme,
port: port_to_integer(port)
)
opts ++ :proplists.delete(:port, scheme_opts)
end
@doc false
def default_fetch_backends do
case Application.fetch_env(:main_proxy, :backends) do
{:ok, backends} ->
backends
:error ->
Logger.warning(
"No backends specified. Either configure :main_proxy, :backends or define a " <>
"`backend/0` function in your `Proxy` module."
)
end
end
# :undefined is what :proplist.get_value returns
defp port_to_integer(:undefined),
do: raise("port is missing from the main_proxy configuration")
defp port_to_integer(port) when is_binary(port), do: String.to_integer(port)
defp port_to_integer(port) when is_integer(port), do: port
end