README

Leaps API

This document outlines the potential Leaps API request/responses in JSON format. Transport between the client and server is asynchronous, and currently implemented with websockets.

To begin a connection the client must connect to the endpoint: ws://<server>:<port>/leaps/ws?username=<username>, note that the username is added to the URL in the query params.

Once the websockets connection is established the server/client communications are confined to the following JSON format:

{
	"type": "<string>",
	"body": {
		"error": {
			"type": "<string>",
			"message": "<string>"
		},
		"client": {
			"username": "<string>",
			"session_id": "<string>"
		},
		"transform": {
			"insert": "<string>",
			"position": "<int>",
			"num_delete": "<int>"
		},
		"correction": {
			"version": "<int>"
		},
		"metadata": {
			"type": "<string>",
			"body": "<object>"
		},
		"document": {
			"id": "<string>",
			"content": "<string>",
			"version": "<int>"
		}
	}
}

Request/Response Types

Client Request Types

Clients can send requests of the following types: subscribe, unsubscribe, transform, metadata, global_metadata, ping.

Which perform the following actions:

Subscribe

In order to start editing a document it must be subscribed to. The client makes a subscribe type request which details the document that it intends to edit.

The request looks as follows:

{
	"type": "subscribe",
	"body": {
		"document": {
			"id": "<string, id of document>"
		}
	}
}

The service then will respond with either a subscribe or an error event.

Unsubscribe

When a document subscription is active and the client no longer has an interest in it they can use the unsubscribe request, which looks as follows:

{
	"type": "unsubscribe",
	"body": {
		"document": {
			"id": "<string, id of document>"
		}
	}
}

The service then will respond with either an unsubscribe or an error event.

Transform

When a subscribed document is edited by the client it must submit a transform request, which looks as follows:

{
	"type": "transform",
	"body": {
		"document": {
			"id": "<string, id of target document>"
		},
		"transform": {
			"insert": "<string, text to insert>",
			"position": "<int, position of change>",
			"num_delete": "<int, number of characters to delete>"
		}
	}
}

The service will respond with either a correction or an error event.

Metadata

Sometimes clients need to send their own custom data to other clients. Leaps will route any metadata type of message to other clients subscribed to the same document, which looks as follows:

{
	"type": "metadata",
	"body": {
		"document": {
			"id": "<string, id of target document>"
		},
		"metadata": {
			"type": "<string, type of metadata>",
			"body": "<object, the metadata itself>"
		}
	}
}

The service will not respond to a metadata request unless an error occurs.

Global Metadata

Clients may also send metadata to all users connected to the leaps service, regardless of subscription. This is done with the global_metadata event, which is similar in all other ways to the metadata event, and looks as follows:

{
	"type": "global_metadata",
	"body": {
		"metadata": {
			"type": "<string, type of metadata>",
			"body": "<object, the metadata itself>"
		}
	}
}

The service will not respond to a global_metadata request unless an error occurs.

Ping

Send a ping event to get back a pong event, there is no body to the request so it looks like this:

{
	"type": "ping",
	"body": {}
}
Server Response Types

Servers will send responses of the following types: subscribe, unsubscribe, correction, transforms, metadata, global_metadata, pong.

Which perform the following actions:

Subscribe

When a client makes a subscribe request, and the request is successful, the server will also respond with a subscribe typed response.

The response looks as follows:

{
	"type": "subscribe",
	"body": {
		"document": {
			"id": "<string, id of document>",
			"content": "<string, the current content of the document>",
			"version": "<int, the current version of the document>"
		}
	}
}
Unsubscribe

When a client makes an unsubscribe request, and the request is successful, the server will also respond with an unsubscribe typed response.

The response looks as follows:

{
	"type": "unsubscribe",
	"body": {
		"document": {
			"id": "<string, id of document>"
		}
	}
}
Correction

When a client submits a transform it is speculative in that the version of the transform is only what the client expects it to be. The server then processes the transform, corrects it, and then responds with a correction typed response of the following format:

{
	"type": "correction",
	"body": {
		"document": {
			"id": "<string, id of document>"
		},
		"correction": {
			"version": "<int, the actual version of the last submitted transform>"
		}
	}
}
Transforms

A document transform submitted by a client will be broadcast to all other subscribed clients. Those clients receive a transforms typed message, as this message may potentially contain multiple transforms.

The response looks as follows:

{
	"type": "transforms",
	"body": {
		"document": {
			"id": "<string, id of document>"
		},
		"transforms": [
			{
				"insert": "<string, text to insert>",
				"position": "<int, position of change>",
				"num_delete": "<int, number of characters to delete>"
			}
		]
	}
}

The service will respond with either a correction or an error event.

Metadata

Metadata submitted from subscribed clients are broadcast to all other subscribed clients in the same format with additional client identifying information:

{
	"type": "metadata",
	"body": {
		"client": {
			"username": "<string, username of the source client>",
			"session_id": "<string, unique uuid of the source client>"
		},
		"document": {
			"id": "<string, id of document>"
		},
		"metadata": {
			"type": "<string, type of metadata>",
			"body": "<object, the metadata itself>"
		}
	}
}
Global Metadata

Global metadata submitted from clients are broadcast to all other connected clients in the same format with additional client identifying information:

{
	"type": "global_metadata",
	"body": {
		"client": {
			"username": "<string, username of the source client>",
			"session_id": "<string, unique uuid of the source client>"
		},
		"metadata": {
			"type": "<string, type of metadata>",
			"body": "<object, the metadata itself>"
		}
	}
}

There are a number of global_metadata events that the server sends automatically during a connection, such as user_info. To read about these events, as well as any established client events, you can read the metadata spec here.

Pong

Sent back after receiving a ping request.

{
	"type": "pong",
	"body": {}
}
Expand ▾ Collapse ▴

Documentation

Overview

    Package api - Contains network API implementations.

    Index

    Constants

    This section is empty.

    Variables

    This section is empty.

    Functions

    This section is empty.

    Types

    type CMDBroker

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

      CMDBroker - The leaps API allows the service owner to specify a static list of available commands. The broker is responsible for providing each new client the list of commands, then listens for requests by the client to run those commands. When a command is run the broker broadcasts the output to all connected clients.

      func NewCMDBroker

      func NewCMDBroker(
      	cmds []string,
      	cmdRunner CMDRunner,
      	timeout time.Duration,
      	logger log.Modular,
      	stats metrics.Type,
      ) *CMDBroker

        NewCMDBroker - Create a new instance of an event broker.

        func (*CMDBroker) Close

        func (b *CMDBroker) Close(time.Duration)

          Close initiates the shut down of the background cmd runner.

          func (*CMDBroker) NewEmitter

          func (b *CMDBroker) NewEmitter(username, uuid string, e Emitter)

            NewEmitter - Register a new emitter to the broker, the emitter will begin receiving globally broadcast events from other emitters.

            type CMDRunner

            type CMDRunner interface {
            	// CMDRun runs the provided command in a shell and returns the result.
            	CMDRun(cmd string) (stdout, stderr []byte, err error)
            }

              CMDRunner is a type that executes commands, returning separate stdout/stderr results as well as an error.

              type CuratorSession

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

                CuratorSession - An API gateway between a client and a leaps curator. This gateway is responsible for tracking a client session as it attempts to create, connect to and edit documents.

                func NewCuratorSession

                func NewCuratorSession(
                	username, uuid string,
                	emitter Emitter,
                	cur curator.Type,
                	timeout time.Duration,
                	logger log.Modular,
                	stats metrics.Type,
                ) *CuratorSession

                  NewCuratorSession - Creates a curator gateway API for a user IO session that binds to events from the provided network IO emitter. Currently the API is limited to single document access, this could, however, be changed later.

                  type Emitter

                  type Emitter interface {
                  
                  	// OnReceive - Register a handler for a particular incoming event type.
                  	OnReceive(reqType string, handler RequestHandler)
                  
                  	// OnSend - Register a handler for a particular outgoing event type.
                  	OnSend(resType string, handler ResponseHandler)
                  
                  	// OnClose - Register an event handler for a close event.
                  	OnClose(eventHandler EventHandler)
                  
                  	// Send - Send data out to the client.
                  	Send(resType string, body interface{}) error
                  }

                    Emitter - To be instantiated for each connected client. Allows components to implement the leaps service API by registering their request and event handlers. The emitter then handles networked traffic and brokers incoming requests to those registered components. All incoming messages are expected to be of the JSON format:

                    {
                      "type": "<type_string>",
                      "body": {...}
                    }
                    

                    Handlers for request types are given the unparsed JSON body of the request. It is guaranteed that events will NOT be triggered in parallel, although they are not guaranteed to come from the same goroutine.

                    type EventHandler

                    type EventHandler func()

                      EventHandler - Called on a connection related event (open, close, etc)

                      type GlobalMetadataBroker

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

                        GlobalMetadataBroker - The leaps API defines events that are outside of the functionality of curators and binders, such as chat messages and user join/leave notifications. The GlobalMetadataBroker implements these functions by managing references to open Emitters.

                        func NewGlobalMetadataBroker

                        func NewGlobalMetadataBroker(
                        	timeout time.Duration,
                        	logger log.Modular,
                        	stats metrics.Type,
                        ) *GlobalMetadataBroker

                          NewGlobalMetadataBroker - Create a new instance of an event broker.

                          func (*GlobalMetadataBroker) NewEmitter

                          func (b *GlobalMetadataBroker) NewEmitter(username, uuid string, e Emitter)

                            NewEmitter - Register a new emitter to the broker, the emitter will begin receiving globally broadcast events from other emitters.

                            type RequestHandler

                            type RequestHandler func(body []byte) events.TypedError

                              RequestHandler - Called when a request has been received, receives the body of the request and returns a TypedError indicating whether the handler was successful. Errors are sent back to the client.

                              type ResponseHandler

                              type ResponseHandler func(body interface{}) bool

                                ResponseHandler - Called when an outgoing response is about to be sent, receives the body of the response and returns a bool indicating whether the response should be sent (false == do not send).

                                Directories

                                Path Synopsis
                                Package events - Contains string constants and structs for API event and error types.
                                Package events - Contains string constants and structs for API event and error types.
                                Package io - Contains network api.Emitter implementations for io types.
                                Package io - Contains network api.Emitter implementations for io types.