Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/mint/web_socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ defmodule Mint.WebSocket do
connections established by passing `:http` to `Mint.HTTP.connect/4` and
`:wss` corresponding to `:https`.

The WebSocket handshake headers are subject to the `:case_sensitive_headers`
option of `Mint.HTTP.connect/4`: they are lowercased by default and sent in
their conventional casing (`Sec-WebSocket-Key` and friends) when that option
is enabled.

## Options

* `:extensions` - a list of extensions to negotiate. See the extensions
Expand Down
16 changes: 9 additions & 7 deletions lib/mint/web_socket/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@ defmodule Mint.WebSocket.Utils do
:crypto.strong_rand_bytes(16) |> Base.encode64()
end

# header names are written in their conventional casing: Mint lowercases them
# unless the connection was opened with `case_sensitive_headers: true`
def headers({:http1, nonce}, extensions) when is_binary(nonce) do
[
{"upgrade", "websocket"},
{"connection", "upgrade"},
{"sec-websocket-version", "13"},
{"sec-websocket-key", nonce},
{"sec-websocket-extensions", extension_string(extensions)}
{"Upgrade", "websocket"},
{"Connection", "upgrade"},
{"Sec-WebSocket-Version", "13"},
{"Sec-WebSocket-Key", nonce},
{"Sec-WebSocket-Extensions", extension_string(extensions)}
]
|> Enum.reject(fn {_k, v} -> v == "" end)
end

def headers(:http2, extensions) do
[
{"sec-websocket-version", "13"},
{"sec-websocket-extensions", extension_string(extensions)}
{"Sec-WebSocket-Version", "13"},
{"Sec-WebSocket-Extensions", extension_string(extensions)}
]
|> Enum.reject(fn {_k, v} -> v == "" end)
end
Expand Down
38 changes: 38 additions & 0 deletions test/mint/web_socket_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,44 @@ defmodule Mint.WebSocketTest do
end
end

describe "given an HTTP/1 connection to a socket which captures the request" do
setup do
{:ok, listen_socket} = :gen_tcp.listen(0, [:binary, active: false, reuseaddr: true])
on_exit(fn -> :gen_tcp.close(listen_socket) end)
{:ok, port} = :inet.port(listen_socket)

[listen_socket: listen_socket, port: port]
end

test "the upgrade headers are lowercased by default", c do
{:ok, conn} = HTTP1.connect(:http, "localhost", c.port)
{:ok, _conn, _ref} = WebSocket.upgrade(:ws, conn, "/", [])

request = capture_request(c.listen_socket)
assert request =~ "upgrade: websocket"
assert request =~ "sec-websocket-key: "
end

test "the upgrade headers keep their casing with case_sensitive_headers: true", c do
{:ok, conn} = HTTP1.connect(:http, "localhost", c.port, case_sensitive_headers: true)
{:ok, _conn, _ref} = WebSocket.upgrade(:ws, conn, "/", [])

request = capture_request(c.listen_socket)
assert request =~ "Upgrade: websocket"
assert request =~ "Connection: upgrade"
assert request =~ "Sec-WebSocket-Version: 13"
assert request =~ "Sec-WebSocket-Key: "
end
end

defp capture_request(listen_socket) do
{:ok, socket} = :gen_tcp.accept(listen_socket, 5_000)
{:ok, request} = :gen_tcp.recv(socket, 0, 5_000)
:gen_tcp.close(socket)

request
end

@doc !"""
In Mint 1.5.0+, Mint handles the SETTINGS frame from the server asynchronously
and returns default values for server settings until it is received. So we must
Expand Down
Loading