Skip to content

Commit

Permalink
Update docs about event types, events api authorization (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
mthenw committed Jun 11, 2018
1 parent 83d3405 commit 173ccbd
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 105 deletions.
56 changes: 44 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ yet ready for production applications._
1. [Running the Event Gateway](#running-the-event-gateway)
1. [Motivation](#motivation)
1. [Components](#components)
1. [Event Registry](#event-registry)
1. [Function Discovery](#function-discovery)
1. [Subscriptions](#subscriptions)
1. [Spaces](#spaces)
1. [CloudEvents Support](#cloudevents-support)
1. [SDKs](#sdks)
1. [Versioning](#versioning)
1. [FAQ](#faq)
Expand All @@ -46,6 +48,8 @@ yet ready for production applications._
## Reference

1. [API](./docs/api.md)
1. [Event Types](./docs/event-types.md)
1. [Subscription Types](./docs/subscription-types.md)
1. [Architecture](./docs/architecture.md)
1. [Clustering](./docs/clustering.md)
1. [System Events and Plugin System](./docs/system-events-and-plugin-system.md)
Expand Down Expand Up @@ -105,6 +109,12 @@ please check [Running Locally](./docs/running-locally.md) and [Developing](./doc

## Components

### Event Registry

Event Registry is a single source of truth about events occuring in the space. Every event emitted to a space has to have event
type registered beforehand. Event Registry also provides a way to authorize incoming events. Please check
[Event Types](./docs/event-types.md) reference for more information.

### Function Discovery

Discover and call serverless functions from anything that can reach the Event Gateway. Function Discovery supports the
Expand Down Expand Up @@ -162,8 +172,11 @@ teams, eliminates effort spent redeploying functions, and allows you to easily s
HTTP services, even different cloud providers. Functions may be registered as subscribers to a custom event.
When an event occurs, all subscribers are called asynchronously with the event as its argument.

Creating a subscription requires providing ID of registered function, an event type and a path (`/` by default). The
path property indicated URL path which Events API will be listening on.
Creating a subscription requires providing ID of registered function, an event type, an HTTP method (`POST` by default),
and a path (`/` by default). The method and path properties defines HTTP endpoint which Events API will be listening on.

Event Gateway supports two subscription types: `async` and `sync`. Please check [Subscription Types](./docs/subscription-types.md)
reference for more information.

#### Example: Subscribe to an Event

Expand Down Expand Up @@ -207,8 +220,15 @@ eventGateway.subscribe({
curl --request POST \
--url http://localhost:4000/ \
--header 'content-type: application/json' \
--header 'event: user.created' \
--data '{ "name": "Max" }'
--data '{
"eventType": "myapp.user.created",
"eventID": "66dfc31d-6844-42fd-b1a7-a489a49f65f3",
"cloudEventsVersion": "0.1",
"source": "/myapp/services/users",
"eventTime": "1990-12-31T23:59:60Z",
"data": { "userID": "123" },
"contentType": "application/json"
}'
```

</details>
Expand All @@ -218,19 +238,21 @@ curl --request POST \
```javascript
const eventGateway = new EventGateway({ url: 'http://localhost' })
eventGateway.emit({
event: 'user.created',
data: { name: 'Max' }
"eventType": "myapp.user.created",
"eventID": "66dfc31d-6844-42fd-b1a7-a489a49f65f3",
"cloudEventsVersion": "0.1",
"source": "/myapp/services/users",
"eventTime": "1990-12-31T23:59:60Z",
"data": { "userID": "123" },
"contentType": "application/json"
})
```
</details>

#### Sync subscriptions via HTTP event

Custom event subscriptions are asynchronous. There is a special `http` event type for creating synchronous
subscriptions. `http` event is an HTTP request received to specified path and for specified HTTP method. There can be
only one `http` subscription for the same `method` and `path` pair.
#### Example: Subscribe to an `http.request` Event

#### Example: Subscribe to an "http" Event
Not all data are events that's why Event Gateway has a special, built-in [`http.request` event type](./docs/api.md#http-request-event) that enables subscribing to
raw HTTP requests.

<details open>
<summary>curl example</summary>
Expand Down Expand Up @@ -285,6 +307,16 @@ Technically speaking Space is a mandatory field ("default" by default) on Functi
to provide during function registration or subscription creation. Space is a first class concept in Config API. Config
API can register function in specific space or list all functions or subscriptions from a space.

## CloudEvents Support

Event Gateway has the first-class support for [CloudEvents](https://cloudevents.io/). It means few things.

First of all, if the event emitted to the Event Gateway is in CloudEvents format, the Event Gateway is able to recognize it and trigger proper subscriptions based on event type specified in the event. Event Gateway supports both Structured Content and Binary Content modes described in [HTTP Transport Binding spec](https://github.com/cloudevents/spec/blob/master/http-transport-binding.md).

Secondly, there is a special, built-in [HTTP Request Event](./docs/api.md#http-request-event) type allowing reacting to raw HTTP requests that are not formatted according to CloudEvents spec. This event type can be especially helpful for building REST APIs.

Currently, Event Gateway supports [CloudEvents v0.1 schema](https://github.com/cloudevents/spec/blob/master/spec.md) specification.

## SDKs

* [SDK for Node.js](https://github.com/serverless/event-gateway-sdk)
Expand Down
192 changes: 140 additions & 52 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,39 @@ This document contains the API documentation for both Events and Configuration A
## Contents

1. [Events API](#events-api)
1. [Event Definition](#event-definition)
1. [How To Emit an Event](#how-to-emit-an-event)
1. [HTTP Request Event](#http-request-event)
1. [Legacy Mode](#legacy-mode)
1. [Configuration API](#configuration-api)
1. [Event Types](#event-types)
1. [Register Event Type](#register-event-type)
1. [Update Event Type](#update-event-type)
1. [Delete Event Type](#delete-event-type)
1. [Get Event Types](#get-event-types)
1. [Get Event Type](#get-event-type)
1. [Functions](#functions)
1. [Register Function](#register-function)
1. [Update Function](#update-function)
1. [Delete Function](#delete-function)
1. [Get Functions](#get-functions)
1. [Get Function](#get-function)
1. [Subscriptions](#subscriptions)
1. [Create Subscription](#create-subscription)
1. [Update Subscription](#update-subscription)
1. [Delete Subscription](#delete-subscription)
1. [Get Subscriptions](#get-subscriptions)
1. [Get Subscription](#get-subscription)
1. [Prometheus Metrics](#prometheus-metrics)
1. [Status](#status)

## Events API

[OpenAPI spec](./openapi/openapi-events-api.yaml)

The Event Gateway exposes an API for emitting events. Events API can be used for emitting custom event, HTTP events and
for invoking function. By default Events API runs on `:4000` port.
The Event Gateway exposes an API for emitting events. By default Events API runs on `:4000` port.

### Event Definition

All data that passes through the Event Gateway is formatted as a CloudEvent, based on [CloudEvents v0.1 schema](https://github.com/cloudevents/spec/blob/master/spec.md):
All data that passes through the Event Gateway is formatted as a CloudEvent, based on [CloudEvents v0.1 schema](https://github.com/cloudevents/spec/blob/master/spec.md).

Example:

Expand All @@ -33,19 +54,29 @@ Example:
}
```

When an event occurs, all subscribers are called with the event in above schema as its argument.
### How To Emit an Event

#### Event Data Type
Creating a subscription requires `path` (default: `/`), `method` (default: `POST`) and `eventType`. `path` indicates path under which you can send the event.

The MIME type of the data block can be specified using the `Content-Type` header (by default it's
`application/octet-stream`). This allows the event gateway to understand how to deserialize the data block if it needs
to. In case of `application/json` type the event gateway passes JSON payload to the target functions. In any other case
the data block is base64 encoded.
**Endpoint**

`POST <Events API URL>/<Subscription Path>`

**Request**

CloudEvents payload

#### HTTP Request Event
**Response**

Status code:

* `202 Accepted` - this status code is returned if there is no [`sync` subscription](./subscription-types.md) defined. Otherwise, status code is controlled by function synchronously subscribed on this endpoint.

### HTTP Request Event

`http.request` event is a built-in type of event occurring for HTTP requests on paths defined in HTTP subscriptions. The
`data` field of an `http.request` event has the following structure:
Not all data are events that's why Event Gateway has a special, built-in `http.request` event type that enables subscribing to
raw HTTP requests. It's especially helpful for building REST APIs or supporting legacy payloads. `http.request` event is a
CloudEvent created by Event Gateway where `data` field has the following structure:

* `path` - `string` - request path
* `method` - `string` - request method
Expand All @@ -55,84 +86,141 @@ the data block is base64 encoded.
* `params` - `object` - matched path parameters
* `body` - depends on `Content-Type` header - request payload

### Emit a Custom Event
### Legacy Mode

Creating a subscription requires `path` property (by default it's "/"). `path` indicates path under which you can push an
event.
*Legacy mode is deprecated and will be removed in upcoming releases.*

**Endpoint**
In legacy mode, Event Gateway is able to recognize event type based on `Event` header. If the event is not formatted according to CloudEvents specification Event Gateway looks for this header and creates CloudEvent internally. In this case, whole request body is put into `data` field.

`POST <Events API URL>/<Subscription Path>`
#### Event Data Type

The MIME type of the data block can be specified using the `Content-Type` header (by default it's
`application/octet-stream`). This allows the Event Gateway to understand how to deserialize the data block if it needs
to. In case of `application/json` type the Event Gateway passes JSON payload to the target functions. In any other case
the data block is base64 encoded.

## Configuration API

[OpenAPI spec](./openapi/openapi-config-api.yaml)

**Request Headers**
The Event Gateway exposes a RESTful JSON configuration API. By default Configuration API runs on `:4001` port.

### Event Types

#### Register Event Type

**Endpoint**

* `Event` - `string` - required, event name
* `Content-Type` - `MIME type string` - payload type
`POST <Configuration API URL>/v1/spaces/<space>/eventtypes`

**Request**

arbitrary payload, subscribed function receives an event in Event schema
JSON object:

* `name` - `string` - required, event type name
* `authorizerId` - `string` - authorizer function ID

**Response**

Status code:

* `202 Accepted`
* `201 Created` on success
* `400 Bad Request` on validation error

JSON object:

### Emit an HTTP Event
* `space` - `string` - space name
* `name` - `string` - event type name
* `authorizerId` - `string` - authorizer function ID

Creating HTTP subscription requires `method` and `path` properties. Those properties are used to listen for HTTP events.
---

#### Update Event Type

**Endpoint**

`<method> <Events API URL>/<path>`
`PUT <Configuration API URL>/v1/spaces/<space>/eventtypes/<event type name>`

**Request**

arbitrary payload, subscribed function receives an event in [HTTP Event](#http-event) schema.
JSON object:

* `authorizerId` - `string` - authorizer function ID

**Response**

HTTP subscription response depends on [response object](#respond-to-an-http-request-event) returned by the backing function. In case of failure during function invocation following error response are possible:
Status code:

* `200 OK` on success
* `400 Bad Request` on validation error or if the authorizer function doesn't exist
* `404 Not Found` if event type doesn't exist

JSON object:

* `404 Not Found` if there is no backing function registered for requested HTTP endpoint
* `500 Internal Server Error` if the function invocation failed or the backing function didn't return [HTTP response object](#respond-to-an-http-request-event)
* `space` - `string` - space name
* `name` - `string` - event type name
* `authorizerId` - `string` - authorizer function ID

#### Path parameters
---

The Event Gateway allows creating HTTP subscription with parameterized paths. Every path segment prefixed with `:` is
treated as a parameter, e.g. `/users/:id`.
#### Delete Event Type

The Event Gateway prevents from creating subscriptions in following conflicting situations:
Delete event type. This operation fails if there is at least one subscription using the event type.

**Endpoint**

* registering static path when there is parameterized path registered already (`/users/:id` vs. `/users/foo`)
* registering parameterized path with different parameter name (`/users/:id` vs. `/users/:name`)
`DELETE <Configuration API URL>/v1/spaces/<space>/eventtypes/<event type name>`

Key and value of matched parameters are passed to a function in an HTTP Event under `params` field.
**Response**

##### Wildcard parameters
Status code:

Special type of path parameter is wildcard parameter. It's a path segment prefixed with `*`. Wildcard parameter can only
be specified at the end of the path and will match every character till the end of the path. For examples
parameter `/users/*userpath` for request path `/users/group1/user1` will match `group1/user1` as a `userpath` parameter.
* `204 No Content` on success
* `400 Bad Request` if there are subscriptions using the event type
* `404 Not Found` if event type doesn't exist

#### Respond to an HTTP Request Event
---

To respond to an HTTP event a function needs to return object with following fields:
#### Get Event Types

* `statusCode` - `int` - response status code, default: 200
* `headers` - `object` - response headers
* `body` - `string` - required, response body
**Endpoint**

Currently, the event gateway supports only string responses.
`GET <Configuration API URL>/v1/spaces/<space>/eventtypes`

## Configuration API
**Response**

[OpenAPI spec](./openapi/openapi-config-api.yaml)
Status code:

* `200 OK` on success

JSON object:

* `eventTypes` - `array` of `object` - event types:
* `space` - `string` - space name
* `name` - `string` - event type name
* `authorizerId` - `string` - authorizer function ID

#### Get Event Type

**Endpoint**

`GET <Configuration API URL>/v1/spaces/<space>/eventtypes/<event type name>`

**Response**

Status code:

* `200 OK` on success
* `404 Not Found` if event type doesn't exist

JSON object:

* `space` - `string` - space name
* `name` - `string` - event type name
* `authorizerId` - `string` - authorizer function ID

The Event Gateway exposes a RESTful JSON configuration API. By default Configuration API runs on `:4001` port.

### Function Discovery
### Functions

#### Register Function

Expand Down
Loading

0 comments on commit 173ccbd

Please sign in to comment.