Packages
bandit
1.4.2
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/websocket/upgrade_validation.ex
defmodule Bandit.WebSocket.UpgradeValidation do
@moduledoc false
# Provides validation of WebSocket upgrade requests as described in RFC6455§4.2
# Validates that the request satisfies the requirements to issue a WebSocket upgrade response.
# Validations are performed based on the clauses laid out in RFC6455§4.2
#
# This function does not actually perform an upgrade or change the connection in any way
#
# Returns `:ok` if the connection satisfies the requirements for a WebSocket upgrade, and
# `{:error, reason}` if not
#
@spec validate_upgrade(Plug.Conn.t()) :: :ok | {:error, String.t()}
def validate_upgrade(conn) do
case Plug.Conn.get_http_protocol(conn) do
:"HTTP/1.1" -> validate_upgrade_http1(conn)
other -> {:error, "HTTP version #{other} unsupported"}
end
end
# Validate the conn per RFC6455§4.2.1
defp validate_upgrade_http1(conn) do
with :ok <- assert_method(conn, "GET"),
:ok <- assert_header_nonempty(conn, "host"),
:ok <- assert_header_contains(conn, "connection", "upgrade"),
:ok <- assert_header_contains(conn, "upgrade", "websocket"),
:ok <- assert_header_nonempty(conn, "sec-websocket-key"),
:ok <- assert_header_equals(conn, "sec-websocket-version", "13") do
:ok
end
end
defp assert_method(conn, verb) do
case conn.method do
^verb -> :ok
other -> {:error, "HTTP method #{other} unsupported"}
end
end
defp assert_header_nonempty(conn, header) do
case Plug.Conn.get_req_header(conn, header) do
[] -> {:error, "'#{header}' header is absent"}
_ -> :ok
end
end
defp assert_header_equals(conn, header, expected) do
case Plug.Conn.get_req_header(conn, header) |> Enum.map(&String.downcase(&1, :ascii)) do
[^expected] -> :ok
value -> {:error, "'#{header}' header must equal '#{expected}', got #{inspect(value)}"}
end
end
defp assert_header_contains(conn, header, needle) do
haystack = Plug.Conn.get_req_header(conn, header)
haystack
|> Enum.flat_map(&Plug.Conn.Utils.list/1)
|> Enum.any?(&(String.downcase(&1, :ascii) == needle))
|> case do
true -> :ok
false -> {:error, "'#{header}' header must contain '#{needle}', got #{inspect(haystack)}"}
end
end
end