pubs

package
v0.15.2-0...-1d34bd1 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2021 License: AGPL-3.0-only Imports: 25 Imported by: 0

README

Kopano API pubs plugin

The pubs plugin provides a simple pub/sub system with HTTP webhooks and websocket stream subscription.

Configuration

For security, the pubs plugin needs a secret key so it can HMAC its tokens. By default a random 512 bit secret key is generated on startup. For production use the key should not change and can be provided as hex encoded value by the KOPANO_PUBS_SECRET_KEY environment variable. A suitable key value can be created with with openssl rand -hex 64.

KOPANO_PUBS_ALLOW_CORS is an environment variable which if set to 1 enables CORS (Cross Origin Resource Sharing) HTTP requests and headers so that the REST endpoints provided by this plugin can be used from a browser cross origin.

KOPANO_PUBS_REQUIRED_SCOPES is an environment variable which defines the required access token scopes to grant access to the API endpoints provided by this plugin. By default the scopes are kopano/pubs.

HTTP API v1

The base URL to this API is /api/pubs/v1. All example URLs are sub paths of this base URL.

Authentication

All endpoints of the Pubs API require OAuth2 Bearer authentication with an access token (if not stated otherwise).

Register webhook pub URL

Registers a new webhook URL to publish data to a certain topic.

POST /webhook?topic=optional-client-provided-topic
201
{
	"id": "${id}",
	"pubUrl": "/api/pubs/v1/webhook/${topic-and-webhook-token-id}",
	"topic": "${topic-as-passed-to-post-or-random}"
}

The id is auto generated by the server and is unique and can be used to reference this webhook. If no topic is provided via the topic request parameter, a unique secure random topic is generated and returned.

Webhook pub

Publish data to a previously registered webhook URL. Authorization and topic are encoded inside the token and cannot be changed. Thus the webhook pub endpoints do not require additional Bearer authentication.

POST /webhook/${id}/${topic-and-webhook-token}
POST /webhook/${id}/${topic-and-webhook-token}/${envelope}
204

Optionally the data is enclosed into a JSON structure with a type matching the value of the subpath envelope.

Websocket bi-directional event stream

Websocket stream can be used to interact with pubs pub/sub. To retrieve the address for Websocket streaming, issue an authenticated request to the /stream/connect endpoint.

GET /stream/connect
200
{
  "streamUrl": "/api/pubs/v1/stream/websocket/ap1L3rNzuC9uWc07FT3QJCDZ1Q8PjLoV"
}

The streamUrl is a one URL to use for Websocket streaming. It can be used exactly one time. Further connects will result in 404. If the connection is lost, call connect again. The Websocket stream URL does not require Bearer authentication.

GET /stream/${key} (Websocket)
101

The key is part of the URL received from a previous call to /stream/connect.

Websocket payload data
< {
  "type": "hello",
  "info": {
    "ref": "gnP4kvAKhHAd4ZalVDsRVmkvi9nHHYF71vsCz0UcX2k="
  }
}
> {
	"type": "sub"
	"state": "optional-client-controlled-state",
	"data": {
		"topics": ["topic1", "topic2"]
	}
}
< {
  "type": "ack",
  "state": "optional-client-controlled-state"
}
< {
  "type": "event",
  "data": {
    "type": "trigger-controlled-envelope",
    "data": 1
  },
  "info": {
    "ref": "HINSF2ZYw4MIJCVW4EdorffqTAW4tGJEMifd4lsIcy8=",
    "topics": [
      "topic1"
    ]
  }
}

Possible types are hello, ack, sub, unsub, closeTopic, pub and event.

If the payload data contains a state value, then the server replies with an ack type once the action has been exectued. The ack payload includes the state unmodified.

All received event messages, contain an info object, with the ref to the sending entity (if any) and the topics array which tells what topics this message was meant for.

The data value of the event type is entirely controlled by the trigger, and thus is application specific. For simplicity in client implementations it is recommended to always use a JSON object for data together with a type key so applications can easily handle incoming messages.

Usage examples

This assumes you have wscat and curl in your path.

Websocket example:

$ export PUBS_HOST=https://localhost:8428"
$ wscat -n --connect $PUBS_HOST/api/pubs/v1/stream/websocket
connected (press CTRL+C to quit)
< {
  "type": "hello",
  "info": {
    "ref": "qIclxqTjWWh3KkPYwrZaO1uDIjxbSsIGdHscLpWkLg4="
  }
}
> {"type": "sub", "state": "123", "info": {"topics": ["lala"]}}
< {
  "type": "ack",
  "state": "123"
}

Webhook example:

$ export TOKEN_VALUE=<access_token>
$ curl -s -XPOST -H "Authorization: Bearer $TOKEN_VALUE" "$PUBS_HOST/api/pubs/v1/webhook?topic=lala"
{
  "id": "VNEH1P5s6v1mTKGcG4pwKp9GNxp-bqx2r2oB52uCkfM=",
  "topic": "lala",
  "pubUrl": "/api/pubs/v1/webhook/VNEH1P5s6v1mTKGcG4pwKp9GNxp-bqx2r2oB52uCkfM=/MTUxODUyMjc5NnxNdi1CQXdFQkUzZGxZbWh2YjJ0UWRXSlViMnRsYmtSaGRHRUJfNElBQVFJQkFrbEVBUXdBQVFWVWIzQnBZd0VNQUFBQU5fLUNBU3hXVGtWSU1WQTFjeloyTVcxVVMwZGpSelJ3ZDB0d09VZE9lSEF0WW5GNE1uSXliMEkxTW5WRGEyWk5QUUVFYkdGc1lRQT18U84T7M7v3wD5xuO7P4O5WzICbLAUwuxvPDX2Rjpz_Ic="
}
$ curl -s -XPOST -H "Content-Type: application/json" -d '{"some":"data"}' "$PUBS_HOST/api/pubs/v1/webhook/VNEH1P5s6v1mTKGcG4pwKp9GNxp-bqx2r2oB52uCkfM=/MTUxODUyMjc5NnxNdi1CQXdFQkUzZGxZbWh2YjJ0UWRXSlViMnRsYmtSaGRHRUJfNElBQVFJQkFrbEVBUXdBQVFWVWIzQnBZd0VNQUFBQU5fLUNBU3hXVGtWSU1WQTFjeloyTVcxVVMwZGpSelJ3ZDB0d09VZE9lSEF0WW5GNE1uSXliMEkxTW5WRGEyWk5QUUVFYkdGc1lRQT18U84T7M7v3wD5xuO7P4O5WzICbLAUwuxvPDX2Rjpz_Ic="

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Register plugins.RegisterPluginV1 = func() plugins.PluginV1 {
	return &PubsPlugin{}
}

Register is the exported registration entry point as loaded by Kopano API to register plugins.

Functions

func PrettyJSON

func PrettyJSON(data interface{}) ([]byte, error)

PrettyJSON marshals the provided data as JSON.

func WriteJSON

func WriteJSON(rw http.ResponseWriter, code int, data interface{}, contentType string) error

WriteJSON marshals the provided data as JSON and writes it to the provided http.ResponseWriter using the provided HTTP status code and content-type. the nature of this function is that it always writes a HTTP response header. Thus it makes no sense to write another header on error. Resulting errors should be logged and the connection should be closes as it is non-functional.

Types

type PubsPlugin

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

PubsPlugin implements a flexible Webhook system providing a RESTful API to register hooks and a Websocket API for efficient receival.

func (*PubsPlugin) Close

func (p *PubsPlugin) Close() error

Close closes the accociated plugin.

func (*PubsPlugin) HTTPWebsocketHandler

func (p *PubsPlugin) HTTPWebsocketHandler(rw http.ResponseWriter, req *http.Request)

HTTPWebsocketHandler implements the HTTP handler for stream websocket requests.

func (*PubsPlugin) Info

func (p *PubsPlugin) Info() *plugins.InfoV1

Info returns the accociated plugins plugin.Info.

func (*PubsPlugin) Initialize

func (p *PubsPlugin) Initialize(ctx context.Context, errCh chan<- error, srv plugins.ServerV1) error

Initialize initizalizes the accociated plugin.

func (*PubsPlugin) MakeHTTPWebhookPublishHandler

func (p *PubsPlugin) MakeHTTPWebhookPublishHandler(router *mux.Router) http.Handler

MakeHTTPWebhookPublishHandler creates the HTTP handler for registering webhooks.

func (*PubsPlugin) MakeHTTPWebhookRegisterHandler

func (p *PubsPlugin) MakeHTTPWebhookRegisterHandler(router *mux.Router) http.Handler

MakeHTTPWebhookRegisterHandler implements the HTTP handler for registering webhooks.

func (*PubsPlugin) MakeHTTPWebsocketConnectHandler

func (p *PubsPlugin) MakeHTTPWebsocketConnectHandler(router *mux.Router) http.Handler

MakeHTTPWebsocketConnectHandler createss the HTTP handler for rtm.connect.

func (*PubsPlugin) NumActive

func (p *PubsPlugin) NumActive() uint64

NumActive returns the number of the currently active connections.

func (*PubsPlugin) OnBeforeDisconnect

func (p *PubsPlugin) OnBeforeDisconnect(c *connection.Connection, err error) error

OnBeforeDisconnect is called before a connection is closed. An indication why the connection will be closed is provided with the passed error.

func (*PubsPlugin) OnConnect

func (p *PubsPlugin) OnConnect(c *connection.Connection) error

OnConnect is called for new connections.

func (*PubsPlugin) OnDisconnect

func (p *PubsPlugin) OnDisconnect(c *connection.Connection) error

OnDisconnect is called after a connection has closed.

func (*PubsPlugin) OnError

func (p *PubsPlugin) OnError(c *connection.Connection, err error) error

OnError is called, when the provided connection has encountered an error. The provided error is the error encountered. Any return value other than nil, will result in a close of the connection.

func (*PubsPlugin) OnText

func (p *PubsPlugin) OnText(c *connection.Connection, msg []byte) error

OnText is called when the provided connection received a text message. The message payload is provided as []byte in the msg parameter.

func (*PubsPlugin) ServeHTTP

func (p *PubsPlugin) ServeHTTP(rw http.ResponseWriter, req *http.Request) (bool, error)

ServeHTTP serves HTTP requests.

Jump to

Keyboard shortcuts

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