View Source Absinthe.GraphqlWS.Socket behaviour (AbsintheGrahqlWS v0.3.6)

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

options

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

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

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.

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.

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.

Link to this section Types

@type control() :: :ping | :pong

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

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

A websocket frame to send to the client.

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

Return values from handle_init/2.

@type message() :: binary()

JSON that conforms to the graphql-ws protocol.

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

Opcode atoms for messages pushed to the client.

@type 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

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.
@type 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

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.
@type socket() :: t()
@type 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 Callbacks

Link to this callback

handle_init(payload, socket)

View Source (optional)
@callback 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.

In case the user is authenticated through session cookies, the session data may be accessed in the socket's :connect_info field. Note that you need to send a _csrf_token param in the URL to effectively receive the session info (or else the session will be nil). For more information, visit the Phoenix Endpoint docs: https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#socket/3-common-configuration

example

Example

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

  def handle_init(%{"user_id" => user_id}, socket) 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)
@callback 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

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

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
@spec __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
@spec absinthe_pipeline(Absinthe.Schema.t(), Keyword.t()) :: Absinthe.Pipeline.t()

Provides the default absinthe pipeline.

params

Params

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