Packages
bandit
0.7.6
1.12.0
1.11.1
1.11.0
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
retired
1.9.0
1.8.0
1.7.0
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.0
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.0
1.0.0-pre.18
1.0.0-pre.17
1.0.0-pre.16
1.0.0-pre.15
1.0.0-pre.14
1.0.0-pre.13
1.0.0-pre.12
1.0.0-pre.11
1.0.0-pre.10
1.0.0-pre.9
1.0.0-pre.8
1.0.0-pre.7
1.0.0-pre.6
1.0.0-pre.5
1.0.0-pre.4
1.0.0-pre.3
1.0.0-pre.2
1.0.0-pre.1
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.2.3
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
A pure-Elixir HTTP server built for Plug & WebSock apps
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/bandit/initial_handler.ex
defmodule Bandit.InitialHandler do
@moduledoc false
# The initial protocol implementation used for all connections. Switches to a
# specific protocol implementation based on configuration, ALPN negotiation, and
# line heuristics.
use ThousandIsland.Handler
require Logger
# Attempts to guess the protocol in use, returning the applicable next handler and any
# data consumed in the course of guessing which must be processed by the actual protocol handler
@impl ThousandIsland.Handler
def handle_connection(socket, state) do
http_1_enabled = Keyword.get(Map.get(state.opts, :http_1, []), :enabled, true)
http_2_enabled = Keyword.get(Map.get(state.opts, :http_2, []), :enabled, true)
case {http_1_enabled, http_2_enabled, alpn_protocol(socket), sniff_wire(socket)} do
{_, _, _, :likely_tls} ->
Logger.warning("Connection that looks like TLS received on a clear channel")
{:close, state}
{_, true, Bandit.HTTP2.Handler, Bandit.HTTP2.Handler} ->
{:switch, Bandit.HTTP2.Handler, state}
{true, _, Bandit.HTTP1.Handler, {:no_match, data}} ->
{:switch, Bandit.HTTP1.Handler, data, state}
{_, true, :no_match, Bandit.HTTP2.Handler} ->
{:switch, Bandit.HTTP2.Handler, state}
{true, _, :no_match, {:no_match, data}} ->
{:switch, Bandit.HTTP1.Handler, data, state}
_other ->
{:close, state}
end
end
# Returns the protocol as negotiated via ALPN, if applicable
defp alpn_protocol(socket) do
case ThousandIsland.Socket.negotiated_protocol(socket) do
{:ok, "h2"} ->
Bandit.HTTP2.Handler
{:ok, "http/1.1"} ->
Bandit.HTTP1.Handler
_ ->
:no_match
end
end
# Returns the protocol as suggested by received data, if possible
defp sniff_wire(socket) do
case ThousandIsland.Socket.recv(socket, 24) do
{:ok, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"} -> Bandit.HTTP2.Handler
{:ok, <<22::8, 3::8, minor::8, _::binary>>} when minor in [1, 3] -> :likely_tls
{:ok, data} -> {:no_match, data}
{:error, error} -> {:error, error}
end
end
end