Combo.Proxy (combo v0.10.0)

View Source

Proxy requests to other plugs.

Features

  • Multiple adatpers support
  • Plug support
    • general plugs
    • Combo endpoints
  • WebSocket support

Usage

A Combo.Proxy instance is an isolated supervision tree and you can include it in application's supervisor:

# lib/my_app/application.ex
def start(_type, _args) do
  children = [
    # ...
    {Combo.Proxy, Application.fetch_env!(:my_app, MyApp.Proxy)}
  ]

  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Above code requires a piece of configuration:

config :my_app, MyApp.Proxy,
  server: true,
  adapter: Combo.Proxy.BanditAdapter,
  scheme: :http,
  ip: {127, 0, 0, 1},
  port: 4000,
  backends: [
    %{
      plug: HealthCheckPlug,
      path: "/health-check"
    },
    %{
      plug: MyApp.UserWeb.Endpoint,
      path: "/"
    },
    %{
      plug: MyApp.AdminWeb.Endpoint,
      path: "/admin"
    }
  ]

Before used for matching connections, the backends will be sorted by specificity. So feel free to arrange them in whatever way you like.

When using Combo.Proxy with Combo endpoints, it's required to configure the path of endpoints to a proper value. And it's better to configure :server option of endpoints to false, which avoids them serving requests bypassing Combo.Proxy. For example:

config :my_app, MyApp.UserWeb.Endpoint,
  url: [path: "/"],
  server: false

config :my_app, MyApp.AdminWeb.Endpoint,
  url: [path: "/admin"],
  server: false

Options

  • :server - start the web server or not. It is aware of Combo startup arguments, if the application is started with mix combo.serve or iex -S mix combo.serve, this option will be set to true. Default to false.
  • :backends - the list of backends. See following section for more details. Default to [].
  • :adapter - the adapter for web server, Combo.Proxy.Cowboy2Adapter and Combo.Proxy.BanditAdapter are available. Default to Combo.Proxy.BanditAdapter.
  • adapter options - all other options will be put into an keyword list and passed as the options of the adapter. See following section for more details.

About :backends

A valid :backends option is a list of maps, and the keys of maps are:

  • :plug:
    • required
    • typespec: module() | {module(), keyword()}

    • examples:
      • HealthCheckPlug
      • {HealthCheckPlug, []}
      • ...
  • :method:
    • optional
    • typespec: String.t()
    • examples:
      • "GET"
      • "POST"
      • ...
  • :host:
    • optional
    • typespec: String.t() | Regex.t()

    • examples:
      • "example.com"
      • ...
  • :path:
    • optional
    • typespec: String.t()
    • examples:
      • "/admin"
      • "/api"
      • ...
  • :rewrite_path_info:
    • optional
    • typespec: boolean()
    • default: true
    • examples:
      • true
      • false

About adapter options

In the section of Options, we said:

all other options will be put into an keyword list and passed as the options of the adapter.

It means the all options except :server, :backends, :adapter will be passed as the the options of an adapter.

Take Combo.Proxy.Cowboy2Adapter adapter as an example. If we declare the options like:

config :my_app, MyApp.Proxy,
  backends: [
    # ...
  ],
  adapter: Combo.Proxy.Cowboy2Adapter,
  scheme: :http,
  ip: {127, 0, 0, 1},
  port: 4000,
  transport_options: [num_acceptors: 2]

Then following options will be passed to the underlying Plug.Cowboy when initializing Combo.Proxy:

[
  scheme: :http,
  ip: {127, 0, 0, 1},
  port: 4000,
  transport_options: [num_acceptors: 2]
]

For more available adapter options:

Summary

Functions

Returns a specification to start this module under a supervisor.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

start_link(opts)