defmodule Bandit do @moduledoc """ Defines a Bandit server as part of a supervision tree. A typical child spec to start a Bandit server hosting a plug looks like: ``` {Bandit, plug: {MyApp.Plug, :arg_passed_to_plug_init}, options: [port: 4000]} ``` Three options are supported: * `scheme`: One of `:http` or `:https`. If `:https` is supported, you will need to specify `certfile` and `keyfile` in the `transport_options` subsection of `options`. * `plug`: The plug to handle connections. Can be specified as `MyPlug` or `{MyPlug, plug_opts}` * `options`: Options to pass to `ThousandIsland`. For an exhaustive list of options see the `ThousandIsland` documentation, however some common options are: * `port`: The port to bind to. Defaults to 4000 * `num_acceptors`: The number of acceptor processes to run. This is mostly a performance tuning knob and can usually be left at the default value of 10 * `transport_module`: The name of the module which provides basic socket functions. This overrides any value set for `scheme` and is intended for cases where control over the socket at a fundamental is needed. * `transport_options`: A keyword list of options to be passed into the transport socket's listen function """ def child_spec(arg) do {options, illegal_options} = arg |> Keyword.get(:options, []) |> Keyword.split(~w(port num_acceptors transport_module transport_options)a) if illegal_options != [] do raise "Unsupported option(s) in Bandit config: #{inspect(illegal_options)}" end transport_module = case Keyword.get(arg, :scheme, :http) do :http -> ThousandIsland.Transports.TCP :https -> ThousandIsland.Transports.SSL end options = options |> Keyword.put_new(:transport_module, transport_module) |> Keyword.put(:handler_module, Bandit.Handler) |> Keyword.put(:handler_options, plug(arg)) %{ id: Bandit, start: {ThousandIsland, :start_link, [options]} } end defp plug(arg) do arg |> Keyword.fetch!(:plug) |> case do {plug, plug_options} -> {plug, plug.init(plug_options)} plug -> {plug, plug.init([])} end end end