graphql_transport_ws

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 15, 2020 License: MIT Imports: 10 Imported by: 0

README

Go Report Card build

WIP: graphql-transport-ws

A WebSocket client and server for GraphQL.

graphql-transport-ws implements Apollos' "GraphQL over WebSocket" protocol, which can be found in PROTOCOL.md. It provides an RPC-like API for both client and server usage.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewHandler

func NewHandler(h MessageHandler, opts ...ServerOption) http.Handler

NewHandler configures an http.Handler, which will upgrade incoming connections to WebSocket and serve the "graphql-ws" subprotocol.

Types

type Client

type Client interface {
	// Query provides an RPC like API for performing GraphQL queries.
	Query(context.Context, *Request) (*Response, error)
}

Client provides high-level API for making GraphQL requests over WebSocket.

func NewClient

func NewClient(conn *Conn) Client

NewClient takes a connection and initializes a client over it.

Example (Concurrent)
conn, err := Dial(context.TODO(), "ws://example.com")
if err != nil {
	// Make sure to handle the error
	return
}
defer conn.Close()

// Performing queries is completely concurrent safe.
client := NewClient(conn)

respCh := make(chan *Response)
go func() {
	resp, err := client.Query(context.TODO(), &Request{Query: "{ hello { world } }"})
	if err != nil {
		// Remember, always handle errors
		return
	}
	respCh <- resp
}()

go func() {
	resp, err := client.Query(context.TODO(), &Request{Query: "{ hello { world } }"})
	if err != nil {
		// Remember, always handle errors
		return
	}
	respCh <- resp
}()

for resp := range respCh {
	// Always check resp.Errors
	fmt.Println(resp)
}
Output:

Example (Query)
conn, err := Dial(context.TODO(), "ws://example.com")
if err != nil {
	// Make sure to handle the error
	return
}
defer conn.Close()

client := NewClient(conn)

resp, err := client.Query(context.TODO(), &Request{Query: "{ hello { world } }"})
if err != nil {
	// Remember, always handle errors
	return
}
// Always check resp.Errors

var exampleResp struct {
	Hello struct {
		World string `json:"world"`
	} `json:"hello"`
}

err = json.Unmarshal(resp.Data, &exampleResp)
if err != nil {
	return
}

// Now, exampleResp.Hello.World would be your query result.
Output:

type CompressionMode

type CompressionMode websocket.CompressionMode

CompressionMode represents the modes available to the deflate extension. See https://tools.ietf.org/html/rfc7692

A compatibility layer is implemented for the older deflate-frame extension used by safari. See https://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06 It will work the same in every way except that we cannot signal to the peer we want to use no context takeover on our side, we can only signal that they should. It is however currently disabled due to Safari bugs. See https://github.com/nhooyr/websocket/issues/218

const (
	// CompressionNoContextTakeover grabs a new flate.Reader and flate.Writer as needed
	// for every message. This applies to both server and client side.
	//
	// This means less efficient compression as the sliding window from previous messages
	// will not be used but the memory overhead will be lower if the connections
	// are long lived and seldom used.
	//
	// The message will only be compressed if greater than 512 bytes.
	//
	CompressionNoContextTakeover CompressionMode = iota

	// CompressionContextTakeover uses a flate.Reader and flate.Writer per connection.
	// This enables reusing the sliding window from previous messages.
	// As most WebSocket protocols are repetitive, this can be very efficient.
	// It carries an overhead of 8 kB for every connection compared to CompressionNoContextTakeover.
	//
	// If the peer negotiates NoContextTakeover on the client or server side, it will be
	// used instead as this is required by the RFC.
	//
	CompressionContextTakeover

	// CompressionDisabled disables the deflate extension.
	//
	// Use this if you are using a predominantly binary protocol with very
	// little duplication in between messages or CPU and memory are more
	// important than bandwidth.
	//
	CompressionDisabled
)

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a client connection that should be closed by the client.

func Dial

func Dial(ctx context.Context, endpoint string, opts ...DialOption) (*Conn, error)

Dial creates a connection to the given endpoint. By default, it's a non-blocking dial (the function won't wait for connections to be established, and connecting happens in the background).

Example
conn, err := Dial(context.TODO(), "ws://example.com")
if err != nil {
	// Make sure to handle the error
	return
}
defer conn.Close()

// Create a single client with the connection.
// There is no need to create multiple connections or clients
// because it will all be managed for you.
Output:

func (*Conn) Close

func (c *Conn) Close() error

Close closes the underlying WebSocket connection.

type ConnOption

type ConnOption interface {
	DialOption
	ServerOption
}

ConnOption represents a configuration that applies symmetrically on both sides, client and server.

func WithCompression

func WithCompression(mode CompressionMode, threshold int) ConnOption

WithCompression configures compression over the WebSocket. By default, compression is disabled and for now is considered an experimental feature.

type DialOption

type DialOption interface {
	SetDial(*dialOpts)
}

DialOption configures how we set up the connection.

func WithHTTPClient

func WithHTTPClient(client *http.Client) DialOption

WithHTTPClient provides an http.Client to override the default one used.

func WithHeaders

func WithHeaders(headers http.Header) DialOption

WithHeaders adds custom headers to every dial HTTP request.

type ErrIO

type ErrIO struct {
	// Msg
	Msg string

	// Err
	Err error
}

ErrIO represents a wrapped I/O error.

func (ErrIO) Error

func (e ErrIO) Error() string

Error implements the error interface.

func (ErrIO) Unwrap

func (e ErrIO) Unwrap() error

Unwrap is for the errors package to use within its As, Is, and Unwrap functions.

type ErrUnexpectedMessage

type ErrUnexpectedMessage struct {
	// Expected was the expected message type.
	Expected string

	// Received was the received message type.
	Received string
}

ErrUnexpectedMessage represents a unexpected message type.

func (ErrUnexpectedMessage) Error

func (e ErrUnexpectedMessage) Error() string

Error implements the error interface.

type MessageHandler

type MessageHandler func(context.Context, *Request) (*Response, error)

MessageHandler is a user provided function for handling incoming GraphQL queries. All other "GraphQL over Websocket" protocol messages are automatically handled internally. All resolvers errors should be included in *Response and any validation error should be returned as error.

type Request

type Request struct {
	Query         string                 `json:"query"`
	Variables     map[string]interface{} `json:"variables"`
	OperationName string                 `json:"operationName"`
}

Request represents a payload sent from the client.

type Response

type Response struct {
	Data   json.RawMessage   `json:"data"`
	Errors []json.RawMessage `json:"errors"`
}

Response represents a payload returned from the server. It supports lazy decoding by leaving the inner data for the user to decode.

type ServerError

type ServerError struct {
	Msg string `json:"msg"`
}

ServerError represents a payload which is sent by the server if it encounters a non-GraphQL resolver error.

func (*ServerError) Error

func (e *ServerError) Error() string

Error implements the error interface.

type ServerOption

type ServerOption interface {
	SetServer(*options)
}

ServerOption allows the user to configure the handler.

func WithOrigins

func WithOrigins(origins ...string) ServerOption

WithOrigins lists the host patterns for authorized origins. The request host is always authorized. Use this to allow cross origin WebSockets.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL