-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cleanup + openapi descriptor for the internal API
- Loading branch information
Showing
2 changed files
with
249 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
openapi: 3.0.3 | ||
info: | ||
title: Neurow Internal API | ||
version: '1.0' | ||
description: | | ||
The Neurow internal API is in charge of receiving messages sent by backends and to push them to frontends that subsribed to them. | ||
It for now provides one single resource: `POST /publish`. | ||
## Authentication | ||
For authentication, the internal API expects a JWT passed in the `authorization` request header as a Bearer Token: | ||
`Authorization: Bearer <JWT>` | ||
The expected properties of this JWT token are: | ||
- Signature algorithm: "HS256", for now only this symmetric algorithm is supported, an asymmetric algorithms like RS256 | ||
will be supported later. | ||
- Required claims: | ||
- "aud": Must be equal to the value configured by `internal_api_authentication.audience` in `runtime.exs` | ||
- "iss": Must equal the name of an issuer configured by `internal_api_authentication.issuers` in `runtime.exs` | ||
- "iat": Must be in the past, | ||
- "exp": Defines a lifetime for the token that cannot be higher than the max lifetime defined by `internal_api_jwt_max_lifetime` in `runtime.exs` | ||
For testing purposes, JWT token can be generated with the following mix task: | ||
``` | ||
mix generate_jwt_token --api=internal --issuer=<issuer_name> | ||
``` | ||
## Publishing messages | ||
A message is defined by a type and a text payload: | ||
```json | ||
{ | ||
"type": "hello", | ||
"payload": "Hello world !" | ||
} | ||
``` | ||
A message can be published to one or multiple topics. To receive messages, frontends need to open a SSE connection on the public API | ||
and to subsribe to the topic where messages were sent. | ||
All topics are automatically namespaced by the issuer defined in the JWT used to authenticate to the internal API and the public API. | ||
For example, if a backend publish a message using the internal API with a JWT with the issuer "my_backend_1", to receive its messages, the frontend | ||
must authenticate with an JWT with the issuer "my_backend_1". | ||
This way of isolating issuers allows the usage of the same Neurow cluster from multiple backends without any risk of collision of between message types, | ||
and by preventing the security risk of having a frontend that subscribes to messages sent by another backends. | ||
Messages are published by sending a JSON payload with a POST on `/subscribe`: | ||
```json | ||
{ | ||
"topic": "user:123", | ||
"message": { | ||
"type": "hello", | ||
"payload": "Hello world !" | ||
} | ||
} | ||
``` | ||
A message can be posted to one single topic, or posted to multiple topics with one single call to the `/publish` resource. Just pass the list | ||
of topics as an array: | ||
```json | ||
{ | ||
"topics": ["user:123", "user:456"] | ||
"message": { | ||
"type": "hello", | ||
"payload": "Hello world !" | ||
} | ||
} | ||
``` | ||
It also possible to publish multiple messages in one HTTP call to `/publish`. Just pass an array of messages: | ||
```json | ||
{ | ||
"topics": ["user:123", "user:456"] | ||
"messages": [ | ||
{ | ||
"type": "hello", | ||
"payload": "Hello world !" | ||
}, | ||
{ | ||
"type": "welcome", | ||
"payload": "Welcome on Neurow" | ||
} | ||
] | ||
} | ||
``` | ||
Here, the two messages are published on two topics. | ||
In response, the internal API return a simple JSON response with the number of message publications: | ||
```json | ||
{"nb_published": 4} | ||
``` | ||
## Timestamping | ||
By default, messages are timestamped with timestamps generated by the internal API when it receives messages. | ||
Message timestamps are forwarded to frontend and can be used in the frontend to decide how to react messages from Neurow | ||
it is has a newer version of the impacted data. | ||
The internal API also allow to define a timestamp (in milliseconds) for each published message: | ||
```json | ||
{ | ||
"type": "hello", | ||
"payload": "Hello world !", | ||
"timestamp": 1516239022123 | ||
} | ||
``` | ||
This timestamp is also used for messages retentions. | ||
## Error management | ||
All errors are described as JSON responses. On errors, the internal API returns an array of errors: | ||
```json | ||
{ | ||
errors: [ | ||
{"error_code": "code1", "error_message": "Description message 1"}, | ||
{"error_code": "code2", "error_message": "Description message 2"}, | ||
] | ||
} | ||
``` | ||
Error codes are stable and can be used for error management in the system that call the internal API. Error messages give | ||
more detailed about the problem and are | ||
provided for investigation, they should not be used to implement error management in the system that calls the internal API. | ||
servers: | ||
- url: http://localhost:3000/v1 | ||
description: Default local development environment whe Neurow is started locally | ||
|
||
paths: | ||
/publish: | ||
post: | ||
security: | ||
- bearerAuth: [] | ||
requestBody: | ||
required: true | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/PublishRequest' | ||
responses: | ||
'200': | ||
description: Success | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/PublishResponse' | ||
'400': | ||
description: Bad request | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/StandardError' | ||
'403': | ||
description: Forbidden | ||
content: | ||
application/json: | ||
schema: | ||
$ref: '#/components/schemas/StandardError' | ||
components: | ||
securitySchemes: | ||
bearerAuth: | ||
type: http | ||
scheme: bearer | ||
bearerFormat: JWT | ||
schemas: | ||
StandardError: | ||
type: object | ||
description: Common structure for all errors. All errors are described with this data structured | ||
properties: | ||
errors: | ||
type: array | ||
items: | ||
type: object | ||
properties: | ||
error_code: | ||
description: Error codes are stable and can be used for error management in the system that call the internal API | ||
type: string | ||
error_message: | ||
description: Error messages give more detailed about the problem and are provided for investigation | ||
type: string | ||
required: | ||
- error_code | ||
- error_message | ||
|
||
PublishResponse: | ||
description: Response returned by the /publish resurce | ||
type: object | ||
required: | ||
- nb_published | ||
properties: | ||
nb_published: | ||
description: Number of messages that was published in Neurow | ||
type: integer | ||
|
||
PublishRequest: | ||
type: object | ||
allOf: | ||
- oneOf: | ||
- required: | ||
- topic | ||
properties: | ||
topic: | ||
type: string | ||
description: Name of the topic where messages are published | ||
- required: | ||
- topics | ||
properties: | ||
topics: | ||
type: array | ||
description: List of topic names where messages are published | ||
items: | ||
type: string | ||
- oneOf: | ||
- required: | ||
- message | ||
properties: | ||
message: | ||
$ref: '#/components/schemas/Message' | ||
- required: | ||
- messages | ||
properties: | ||
messages: | ||
type: array | ||
items: | ||
$ref: '#/components/schemas/Message' | ||
Message: | ||
type: object | ||
required: | ||
- type | ||
- payload | ||
properties: | ||
type: | ||
type: string | ||
payload: | ||
type: object | ||
timestamp: | ||
type: integer | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters