View Source Bandit (Bandit v1.0.0-pre.13)
Bandit is an HTTP server for Plug and WebSock apps.
As an HTTP server, Bandit's primary goal is to act as 'glue' between client connections managed by Thousand Island and application code defined via the Plug and/or WebSock APIs. As such there really isn't a whole lot of user-visible surface area to Bandit, and as a consequence the API documentation presented here is somewhat sparse. This is by design! Bandit is intended to 'just work' in almost all cases; the only thought users typically have to put into Bandit comes in the choice of which options (if any) they would like to change when starting a Bandit server. The sparseness of the Bandit API should not be taken as an indicator of the comprehensiveness or robustness of the project.
Using Bandit With Phoenix
Bandit fully supports Phoenix. Phoenix applications which use WebSockets for features such as Channels or LiveView require Phoenix 1.7 or later.
Using Bandit to host your Phoenix application couldn't be simpler:
Add Bandit as a dependency in your Phoenix application's
mix.exs
:{:bandit, "~> 1.0-pre"}
Add the following
adapter:
line to your endpoint configuration inconfig/config.exs
, as in the following example:# config/config.exs config :your_app, YourAppWeb.Endpoint, adapter: Bandit.PhoenixAdapter, # <---- ADD THIS LINE url: [host: "localhost"], render_errors: ...
That's it! You should now see messages at startup indicating that Phoenix is using Bandit to serve your endpoint, and everything should 'just work'. Note that if you have set any exotic configuration options within your endpoint, you may need to update that configuration to work with Bandit; see the Bandit.PhoenixAdapter documentation for more information.
Using Bandit With Plug Applications
Using Bandit to host your own Plug is very straightforward. Assuming you have
a Plug module implemented already, you can host it within Bandit by adding
something similar to the following to your application's Application.start/2
function:
def start(_type, _args) do
children = [
{Bandit, plug: MyApp.MyPlug}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
For less formal usage, you can also start Bandit using the same configuration
options via the Bandit.start_link/1
function:
# Start an http server on the default port 4000, serving MyApp.MyPlug
Bandit.start_link(plug: MyPlug)
Configuration
A number of options are defined when starting a server. The complete list is
defined by the t:Bandit.options/0
type.
Setting up an HTTPS Server
By far the most common stumbling block encountered when setting up an HTTPS server involves configuring key and certificate data. Bandit is comparatively easy to set up in this regard, with a working example looking similar to the following:
def start(_type, _args) do
children = [
{Bandit,
plug: MyPlug,
scheme: :https,
certfile: "/absolute/path/to/cert.pem",
keyfile: "/absolute/path/to/key.pem"}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
WebSocket Support
If you're using Bandit to run a Phoenix application as suggested above, there is nothing more for you to do; WebSocket support will 'just work'.
If you wish to interact with WebSockets at a more fundamental level, the WebSock and WebSockAdapter libraries provides a generic abstraction for WebSockets (very similar to how Plug is a generic abstraction on top of HTTP). Bandit fully supports all aspects of these libraries.
Summary
Types
Options to configure the deflate library used for HTTP compression
Options to configure the HTTP/1 stack in Bandit
Options to configure the HTTP/2 stack in Bandit
Possible top-level options to configure a Bandit server
Options to configure the WebSocket stack in Bandit
Types
@type deflate_options() :: [ level: :zlib.zlevel(), window_bits: :zlib.zwindowbits(), memory_level: :zlib.zmemlevel(), strategy: :zlib.zstrategy() ]
Options to configure the deflate library used for HTTP compression
@type http_1_options() :: [ enabled: boolean(), max_request_line_length: pos_integer(), max_header_length: pos_integer(), max_header_count: pos_integer(), max_requests: pos_integer(), compress: boolean(), deflate_opions: deflate_options() ]
Options to configure the HTTP/1 stack in Bandit
enabled
: Whether or not to serve HTTP/1 requests. Defaults to truemax_request_line_length
: The maximum permitted length of the request line (expressed as the number of bytes on the wire) in an HTTP/1.1 request. Defaults to 10_000 bytesmax_header_length
: The maximum permitted length of any single header (combined key & value, expressed as the number of bytes on the wire) in an HTTP/1.1 request. Defaults to 10_000 bytesmax_header_count
: The maximum permitted number of headers in an HTTP/1.1 request. Defaults to 50 headersmax_requests
: The maximum number of requests to serve in a single HTTP/1.1 connection before closing the connection. Defaults to 0 (no limit)compress
: Whether or not to attempt compression of responses via content-encoding negotiation as described in RFC9110§8.4. Defaults to truedeflate_options
: A keyword list of options to set on the deflate library. A complete list can be found atdeflate_options/0
@type http_2_options() :: [ enabled: boolean(), max_header_key_length: pos_integer(), max_header_value_length: pos_integer(), max_header_count: pos_integer(), max_requests: pos_integer(), default_local_settings: Bandit.HTTP2.Settings.t(), compress: boolean(), deflate_options: deflate_options() ]
Options to configure the HTTP/2 stack in Bandit
enabled
: Whether or not to serve HTTP/2 requests. Defaults to truemax_header_key_length
: The maximum permitted length of any single header key (expressed as the number of decompressed bytes) in an HTTP/2 request. Defaults to 10_000 bytesmax_header_value_length
: The maximum permitted length of any single header value (expressed as the number of decompressed bytes) in an HTTP/2 request. Defaults to 10_000 bytesmax_header_count
: The maximum permitted number of headers in an HTTP/2 request. Defaults to 50 headersmax_requests
: The maximum number of requests to serve in a single HTTP/2 connection before closing the connection. Defaults to 0 (no limit)default_local_settings
: Options to override the default values for local HTTP/2 settings. Values provided here will override the defaults specified in RFC9113§6.5.2compress
: Whether or not to attempt compression of responses via content-encoding negotiation as described in RFC9110§8.4. Defaults to truedeflate_options
: A keyword list of options to set on the deflate library. A complete list can be found atdeflate_options/0
@type options() :: [ plug: module() | {module(), Plug.opts()}, scheme: :http | :https, port: :inet.port_number(), ip: :inet.socket_address(), keyfile: binary(), certfile: binary(), otp_app: binary() | atom(), cipher_suite: :strong | :compatible, display_plug: module(), startup_log: Logger.level() | false, thousand_island_options: ThousandIsland.options(), http_1_options: http_1_options(), http_2_options: http_2_options(), websocket_options: websocket_options() ]
Possible top-level options to configure a Bandit server
plug
: The Plug to use to handle connections. Can be specified asMyPlug
or{MyPlug, plug_opts}
scheme
: One of:http
or:https
. If:https
is specified, you will also need to specify validcertfile
andkeyfile
values (or an equivalent value withinthousand_island_options.transport_options
). Defaults to:http
port
: The TCP port to listen on. This option is offered as a convenience and actually sets the option of the same name withinthousand_island_options
. If ia string value is passed, it will be parsed as an integer. Defaults to 4000 ifscheme
is:http
, and 4040 ifscheme
is:https
ip
: The interface(s) to listen on. This option is offered as a convenience and actually sets the option of the same name withinthousand_island_options.transport_options
. Can be specified as:{1, 2, 3, 4}
for IPv4 addresses{1, 2, 3, 4, 5, 6, 7, 8}
for IPv6 addresses:loopback
for local loopback (ie:127.0.0.1
):any
for all interfaces (ie:0.0.0.0
){:local, "/path/to/socket"}
for a Unix domain socket. If this option is used, theport
option must be set to0
keyfile
: The path to a file containing the SSL key to use for this server. This option is offered as a convenience and actually sets the option of the same name withinthousand_island_options.transport_options
. If a relative path is used here, you will also need to set theotp_app
parameter and ensure that the named file is part of your application buildcertfile
: The path to a file containing the SSL certificate to use for this server. This option is offered as a convenience and actually sets the option of the same name withinthousand_island_options.transport_options
. If a relative path is used here, you will also need to set theotp_app
parameter and ensure that the named file is part of your application buildotp_app
: Provided as a convenience when using relative paths forkeyfile
andcertfile
cipher_suite
: Used to define a pre-selected set of ciphers, as described byPlug.SSL.configure/1
. Optional, can be either:strong
or:compatible
display_plug
: The plug to use when describing the connection in logs. Useful for situations such as Phoenix code reloading where you have a 'wrapper' plug but wish to refer to the connection by the endpoint namestartup_log
: The log level at which Bandit should log startup info. Defaults to:info
log level, can be set to false to disable itthousand_island_options
: A list of options to pass to Thousand Island. Bandit sets some default values in this list based on your top-level configuration; these values will be overridden by values appearing here. A complete list can be found atThousandIsland.options/0
http_1_options
: A list of options to configure Bandit's HTTP/1 stack. A complete list can be found athttp_1_options/0
http_2_options
: A list of options to configure Bandit's HTTP/2 stack. A complete list can be found athttp_2_options/0
websocket_options
: A list of options to configure Bandit's WebSocket stack. A complete list can be found atwebsocket_options/0
@type websocket_options() :: [ enabled: boolean(), max_frame_size: pos_integer(), validate_text_frames: boolean(), compress: boolean() ]
Options to configure the WebSocket stack in Bandit
enabled
: Whether or not to serve WebSocket upgrade requests. Defaults to truemax_frame_size
: The maximum size of a single WebSocket frame (expressed as a number of bytes on the wire). Defaults to 0 (no limit)validate_text_frames
: Whether or not to validate text frames as being UTF-8. Strictly speaking this is required per RFC6455§5.6, however it can be an expensive operation and one that may be safely skipped in some situations. Defaults to truecompress
: Whether or not to allow per-message deflate compression globally. Note that upgrade requests still need to set thecompress: true
option inconnection_opts
on a per-upgrade basis for compression to be negotiated (see 'WebSocket Support' section below for details). Defaults totrue
Functions
@spec start_link(options()) :: Supervisor.on_start()
Starts a Bandit server using the provided arguments. See options/0
for specific options to
pass to this function.