Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

145 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mint.WebSocket

CI Coverage Status hex.pm version hex.pm license Last Updated

HTTP/1 and HTTP/2 WebSocket support for Mint 🌱

Usage

Mint.WebSocket works together with Mint.HTTP API. For example, this snippet shows sending and receiving a text frame of "hello world" to a WebSocket server which echos our frames:

# bootstrap
{:ok, conn} = Mint.HTTP.connect(:http, "echo", 9000)

{:ok, conn, ref} = Mint.WebSocket.upgrade(:ws, conn, "/", [])

http_get_message = receive(do: (message -> message))
{:ok, conn, [{:status, ^ref, status}, {:headers, ^ref, resp_headers}, {:done, ^ref}]} =
  Mint.WebSocket.stream(conn, http_get_message)

{:ok, conn, websocket} = Mint.WebSocket.new(conn, ref, status, resp_headers)

# send the hello world frame
{:ok, websocket, data} = Mint.WebSocket.encode(websocket, {:text, "hello world"})
{:ok, conn} = Mint.WebSocket.stream_request_body(conn, ref, data)

# receive the hello world reply frame
hello_world_echo_message = receive(do: (message -> message))
{:ok, conn, [{:data, ^ref, data}]} = Mint.WebSocket.stream(conn, hello_world_echo_message)
{:ok, websocket, [{:text, "hello world"}]} = Mint.WebSocket.decode(websocket, data)

Check out some examples and the online documentation.

Functional WebSockets

Mint.WebSocket (like Mint) takes a functional approach. Other WebSocket implementations like :gun / :websocket_client / Socket / WebSockex work by spawning and passing messages among processes. This is a very convenient interface in Erlang and Elixir but it does not allow the author much control over the WebSocket connection.

Instead Mint.WebSocket is process-less: the entire HTTP and WebSocket states are kept in immutable data structures. When you implement a WebSocket client with Mint.WebSocket, runtime behavior and process architecture are up to you: you decide how to handle things like reconnection and failures.

For a practical introduction, check out Mint's usage documentation.

Spec conformance

This library aims to follow RFC6455 and RFC8441 as closely as possible and uses the Autobahn|Testsuite to check conformance with every run of tests/CI. The auto-generated report produced by the Autobahn|Testsuite is uploaded on each push to main.

See the report here: https://elixir-mint.github.io/mint_web_socket/

HTTP/2 Support

HTTP/2 WebSockets are not a built-in feature of HTTP/2. In the current landscape, very few server libraries support the RFC8441's extended CONNECT method which bootstraps WebSockets.

If Mint.WebSocket.upgrade/4 returns

{:error, conn, %Mint.WebSocketError{reason: :extended_connect_disabled}}

Then the server does not support HTTP/2 WebSockets or does not have them enabled.

Development workflow

Contributions are very welcome!

If you're interested in developing Mint.WebSocket, you'll need docker-compose to run the fuzzing test suite. The docker-compose.yml sets up an Elixir container, a simple websocket echo server, and the Autobahn|Testsuite fuzzing server.

In host:

docker-compose up -d
docker-compose exec app bash

In app:

mix deps.get
mix test
iex -S mix

About

HTTP/1 and HTTP/2 WebSocket support for Mint 🌱

Topics

Resources

License

Stars

Watchers

Forks

Contributors