Skip to content

A simple websocket client in Elixir based on the Gun Erlang package

License

Notifications You must be signed in to change notification settings

jeffgrunewald/glock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Glock

Glock is a simple websocket client application based on the Gun HTTP/HTTP2/Websocket Erlang library.

Glock aims to simplify the specific task of starting and configuring a websocket client connection to a remote server, providing common default values for all connection settings provided by Gun while still allowing for full customization.

Glock also provides a set of callbacks for processing messages sent to and received from the remote server and tracking state across the life of the connection in whatever way makes sense to your application. Default callback implementations let you get up and running immediately for simply sending messages to a server and logging received responses by implementing the __using__/1 macro:

Example:

  defmodule MySocket do
    use Glock.Socket
  end

  iex> {:ok, conn} = MySocket.start_link(host: "echo.websocket.org", path: "/")
  {:ok, #PID<0.260.0>}
  iex> :ok = MySocket.push(conn, "hello socket!")

Implementing the init_stream/1 callback allows you to create and store state for the socket connection which can be accessed from subsequent message send or receive events. A simple example might be to count the number of messages sent and received from the socket.

Example:

  defmodule MySocket do
    use Glock.Socket

    def init_stream(conn: conn, protocols: _, headers: _) do
      %{
        "connection" => conn.stream,
        "sent" => 0,
        "received" => 0
      }
    end
  end

Implementing the handle_send/2 callback allows for customization of the message frame types and the encoding or serialization performed on messages prior to sending. Piggy-backing the prior example, a complex data structure could be serialized to JSON and counted before being sent to the remote server.

Example:

  defmodule MySocket do
  ...

    def handle_send(message, state) do
      frame = {:text, JSON.encode(message)}
      new_state = Map.put(state, "sent", state["sent"] + 1)
      {frame, new_state}
    end
  end

Finally, implementing the handle_receive/2 callback allows for custom handling of messages beyond simply logging them. All messages received by the gun connection pass through the handle_receive/2 callback, so you can decode them, store them, reprocess them or anything else you like. This handler also covers receiving :close control frames and cleaning up/ shutting down the glock process appropriately according to the Websocket specification.

Example:

  defmodule MySocket do
  ...

    def handle_receive(frame, state) do
      case frame do
        {:text, message} ->
          send_to_internal_queue(message)
          new_state = Map.put(state, "received", state["received"] + 1)
          {:doesnt_matter, {:ok, new_state}}
        :close ->
          JSON.encode(state) |> write_to_log_service()
          {:close, {:close, state}}
        _ ->
          {:doesnt_matter, {:ok, state}}
      end
    end
  end

Installation

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

def deps do
  [
    {:glock, "~> 0.1.0"}
  ]
end

The docs can be found at https://hexdocs.pm/glock.