Absinthe.GraphqlWS.Socket behaviour (AbsintehGrahqlWS v0.2.1) View Source

This module is used by a custom websocket, which can then handle connections from a client implementing the GraphQL over WebSocket protocol

Options

  • schema - required - The Absinthe schema for the current application (example: MyAppWeb.Schema)
  • keepalive - optional - Interval in milliseconds to send :ping control frames over the websocket. Defaults to 30_000 (30 seconds).
  • pipeline - optional - A {module, function} tuple defining how to generate an Absinthe pipeline for each incoming message. Defaults to {Absinthe.GraphqlWS.Socket, :absinthe_pipeline}.

Pipeline modification

The :pipeline option to socket definition defaults to {Absinthe.GraphqlWS.Socket, :absinthe_pipeline}. This function returns the default pipeline provided by &Absinthe.Pipeline.for_document/2. Absinthe query execution can be modified by altering the list of phases in this pipeline. See Absinthe.Pipeline for more info.

If an alternate pipeline function is provided, it must accept the arguments schema and options. These options include the current context and any variables that are included with the requested query.

Example

defmodule MyAppWeb.GraphqlSocket do
  use Absinthe.GraphqlWS.Socket, schema: MyAppWeb.Schema

  def handle_message(_msg, socket) do
    {:ok, socket}
  end
end

Link to this section Summary

Types

Opcode atoms for messages handled by handle_control/2. Used by server-side keepalive messages.

A websocket frame to send to the client.

Return values from handle_init/2.

JSON that conforms to the graphql-ws protocol.

Opcode atoms for messages pushed to the client.

Valid return values from handle_message/2.

t()

A socket that holds information necessary for parsing incoming messages as well as outgoing subscription data.

Functions

Provides a stub implementation that allows the socket to start. Phoenix.Socket.Transport expects a child spec that starts a process; we do so with a noop Task.

When a client connects to this websocket, this function is called to initialize the socket.

Provides the default absinthe pipeline.

Callbacks

Handle the connection_init message sent by the socket implementation. This will receive the payload from the message, defaulting to an empty map if received from the client.

Handles messages that are sent to this process through send/2, which have not been caught by the default implementation. It must return a reply_message/0.

Link to this section Types

Specs

control() :: :ping | :pong

Opcode atoms for messages handled by handle_control/2. Used by server-side keepalive messages.

Specs

frame() :: {opcode(), message()}

A websocket frame to send to the client.

Specs

init() ::
  {:ok, map(), socket()} | {:error, map(), socket()} | {:stop, term(), socket()}

Return values from handle_init/2.

Specs

message() :: binary()

JSON that conforms to the graphql-ws protocol.

Specs

opcode() :: :text | :binary | control()

Opcode atoms for messages pushed to the client.

Specs

reply_inbound() ::
  {:ok, socket()}
  | {:reply, :ok, frame(), socket()}
  | {:reply, :error, frame(), socket()}
  | {:stop, term(), socket()}

Used internally by Absinthe.GraphqlWS.Transport.handle_in/2.

These are return values to incoming messages from a websocket.

Values

  • {:ok, socket} - save new socket state, without sending any data to the client.
  • {:reply, :ok, {:text, "{}"}, socket} - send JSON content to the client.
  • {:reply, :error, {:text, "{}"}, socket} - send an error with JSON payload to the client.
  • {:stop, :normal, socket} - shut down the socket process.

Specs

reply_message() ::
  {:ok, socket()} | {:push, frame(), socket()} | {:stop, term(), socket()}

Valid return values from handle_message/2.

These are return values to messages that have been received from within Elixir

Values

  • {:ok, socket} - save new socket state, without sending any data to the client.
  • {:push, {:text, Message.Next.new(id, %{})}, socket} - save new socket state, and send data to the client.
  • {:stop, :reason, socket} - stop the socket.

Specs

socket() :: t()

Specs

t() :: %Absinthe.GraphqlWS.Socket{
  absinthe: map(),
  assigns: map(),
  connect_info: map(),
  endpoint: module(),
  handler: term(),
  initialized?: boolean(),
  keepalive: integer(),
  pubsub: term(),
  subscriptions: map()
}

A socket that holds information necessary for parsing incoming messages as well as outgoing subscription data.

Link to this section Functions

Link to this function

__child_spec__(module, opts, socket_opts)

View Source

Provides a stub implementation that allows the socket to start. Phoenix.Socket.Transport expects a child spec that starts a process; we do so with a noop Task.

Link to this function

__connect__(module, socket, options)

View Source

Specs

__connect__(module(), map(), Keyword.t()) :: {:ok, socket()}

When a client connects to this websocket, this function is called to initialize the socket.

Link to this function

absinthe_pipeline(schema, options)

View Source

Specs

absinthe_pipeline(Absinthe.Schema.t(), Keyword.t()) :: Absinthe.Pipeline.t()

Provides the default absinthe pipeline.

Params

  • schema - An Absinthe.Schema.t()
  • options - A keyword list with the current context, variables, etc for the current query.

Link to this section Callbacks

Link to this callback

handle_init(payload, socket)

View Source (optional)

Specs

handle_init(payload :: map(), socket()) :: init()

Handle the connection_init message sent by the socket implementation. This will receive the payload from the message, defaulting to an empty map if received from the client.

This can be used for custom authentication/authorization, using Absinthe.GraphqlWS.Util.assign_context/2 to modify the Absinthe context.

Example

defmodule MySocket do
  use Absinthe.GraphqlWS.Socket, schema: MySchema

  def handle_init(%{"user_id" => user_id}) do
    case find_user(user_id) do
      nil ->
        {:error, %{}, socket}
      user ->
        socket = assign_context(socket, current_user: user)
        {:ok, %{name: user.name}, socket}
    end
  end
end
Link to this callback

handle_message(params, socket)

View Source (optional)

Specs

handle_message(params :: term(), socket()) :: reply_message()

Handles messages that are sent to this process through send/2, which have not been caught by the default implementation. It must return a reply_message/0.

If pushing content to the websocket, it must return a tuple in the form {:push, {:text, message}, socket}, where message is JSON that represents a valid grapql-ws message.

Example

alias Absinthe.GraphqlWS.Message

def handle_message({:thing, thing}, socket) do
  {:ok, assign(socket, :thing, thing)}
end

def handle_message({:send, id, payload}, socket) do
  {:push, {:text, Message.Next.new(id, payload)}, socket}
end

def handle_message(_msg, socket) do
  {:ok, socket}
end