WebSockAdapter

Build Status Docs Hex.pm

WebSockAdapter is a library of adapters from common Web Servers to the WebSock specification. WebSockAdapter currently supports Bandit, Cowboy and Roadrunner, as well as any other Plug adapter whose c:Plug.Conn.Adapter.upgrade/3 call accepts a standard {websock, state, opts} as their third argument when upgrading to a :websocket.

For details on the WebSock specification, consult the WebSock documentation.

Usage

WebSockAdapter makes it easy to upgrade Plug connections to WebSock connections. Here's a simple example:

defmodule EchoServer do
  def init(args) do
    {:ok, []}
  end

  def handle_in({"ping", [opcode: :text]}, state) do
    {:reply, :ok, {:text, "pong"}, state}
  end
end

defmodule MyPlug do
  use Plug.Router

  plug Plug.Logger
  plug :match
  plug :dispatch

  get "/" do
    # Provide the user with some useful instructions to copy & paste into their inspector
    send_resp(conn, 200, """
    Use the JavaScript console to interact using websockets

    sock  = new WebSocket("ws://localhost:4000/websocket")
    sock.addEventListener("message", console.log)
    sock.addEventListener("open", () => sock.send("ping"))
    """)
  end

  get "/websocket" do
    conn
    |> WebSockAdapter.upgrade(EchoServer, [], timeout: 60_000)
    |> halt()
  end

  match _ do
    send_resp(conn, 404, "not found")
  end
end

This simple example illustrates many of the useful features of WebSock / WebSockAdapters:

If you're looking for more detail, Benjamin Milde has a great blog post that goes a bit deeper than the simple example above.

Upgrade Validation

Since 0.5.5, WebSockAdapter validates requests made via WebSockAdapter.upgrade/3 (this was and continues to also be done by the underlying web server, but since the server's validation occurs after the Plug.call/2 lifecycle completes it's difficult to meaningfully handle such errors). This validation examines the request for conformance to the clauses laid out in RFC6455§4.2, as well as RFC8441§5 for HTTP/2 connections. Requests which do not satisfy the requirements laid out in those specifications will result in a WebSockAdapter.UpgradeError being raised, containing details of the reason for the failure

Installation

The websock_adapter package can be installed by adding websock_adapter to your list of dependencies in mix.exs:

def deps do
  [
    {:websock_adapter, "~> 0.5"}
  ]
end

Documentation can be found at https://websock-adapter.hexdocs.pm.

License

MIT