Skip to content

Commit

Permalink
doc improvements - client API overview chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
FZambia committed Dec 27, 2020
1 parent ebdc61b commit 9fce6a1
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 14 deletions.
115 changes: 115 additions & 0 deletions docs/content/server/client_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Client API

This chapter describes client Centrifugo API – i.e. **primitives to communicate with a server from an application front-end** (i.e. browser or mobile device).

This is a formal description – refer to each specific client implementation for concrete method names and possibilities. See [full list of Centrifugo client connectors](../libraries/client.md).

If you are looking for a detailed information about client-server protocol internals then [client protocol description](../transports/protocol.md) chapter can help.

We use Javascript client `centrifuge-js` for examples here.

## Connect

Each Centrifugo client allows connecting to a server.

```javascript
const centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket');
centrifuge.connect();
```

In most cases you will need to pass JWT token for authentication, so the example above transforms to:

```javascript
const centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket');
centrifuge.setToken('<USER-JWT-TOKEN>')
centrifuge.connect();
```

See [authentication](authentication.md) chapter for more information on how to generate connection JWT.

If you are using [connect proxy](proxy.md#connect-proxy) then you may go without setting JWT.

## Disconnect

After connecting you can disconnect from a server at any moment.

```javascript
centrifuge.disconnect();
```

## Connection lifecycle events

All client implementations allow setting handlers on connect and disconnect events.

For example:

```javascript
centrifuge.on('connect', function(connectCtx){
console.log('connected', connectCtx)
});

centrifuge.on('disconnect', function(disconnectCtx){
console.log('disconnected', disconnectCtx)
});
```

## Subscribe

Another core functionality of client API is possibility to subscribe on a channel to receive all messages published to that channel.

```javascript
centrifuge.subscribe('channel', function(messageCtx) {
console.log(messageCtx);
})
```

Client can subscribe to [different channels](channels.md). Subscribe method returns `Subscription` object. It's also possible to react on different Subscription events: join and leave events, subscribe success and subscribe error events, unsubscribe event.

In idiomatic case messages published to channels from application backend [over Centrifugo server API](http_api.md). Though it's not always true.

Centrifugo also provides message recovery feature to restore missed publications in channels. Publications can be missed due to temporary disconnects (bad network) or server reloads. Recovery happens automatically on reconnect (due to bad network or server reloads) as soon as recovery in channel [properly configured](channels.md#channel-options). Client keeps last seen Publication offset and restores new publications since known offset. If recovery failed then client implementation provides flag inside subscribe event to let your application know that some publications missed – so you may need to load state from scratch from application backend. Not all Centrifugo clients implement recovery feature – refer to specific client implementation docs. More details about recovery in [a dedicated chapter](../transports/recovery.md).

## RPC

Client can send RPC to a server. RPC is a call which is not related to channels at all. It's just a way to call server method from client side over WebSocket or SockJS connection. RPC is only available when [RPC proxy](proxy.md#rpc-proxy) configured.

```javascript
const rpcRequest = {'key': 'value'};
const data = await centrifuge.namedRPC('example_method', rpcRequest);
```

## History

Once subscribed client can call publication history inside channel (only for channels where [history configured](channels.md#channel-options)) to get last publications in channel:

```javascript
const resp = await subscription.history();
```

## Presence and presence stats

Once subscribed client can call presence and presence stats information inside channel (only for channels where [presence configured](channels.md#channel-options)):

For presence (full information about active subscribers in channel):

```javascript
const resp = await subscription.presence();
```

For presence stats (just a number of clients and unique users in channel):

```javascript
const resp = await subscription.presenceStats();
```

## Server-side subscriptions

To handle publications coming from [server-side subscriptions](server_subs.md) client API allows listening publications simply on Centrifuge client instance:

```javascript
centrifuge.on('publish', function(messageCtx) {
console.log(messageCtx);
});
```

It's also possible to react on different server-side Subscription events: join and leave events, subscribe success, unsubscribe event. There is no subscribe error event here since subscription initiated on a server side.
16 changes: 6 additions & 10 deletions docs/content/server/http_api.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
# Server HTTP API

HTTP API is a way to send commands to Centrifugo.
HTTP API is a way to send commands to Centrifugo. For example, server API allows publishing messages to channels.

Why we need API?
Server HTTP API works on `/api` endpoint. It has very simple request format: this is a HTTP POST request with `application/json` Content-Type and with JSON command body.

If you look at configuration options you see an option called `publish` defined on configuration top-level and for a channel namespace. When turned on this option allows browser clients to publish into channels directly. If client publishes a message into channel directly – your application will not receive that message (it just goes through Centrifugo towards subscribed clients). This pattern can be useful sometimes but in most cases you first need to send new event from client to backend over non-Centrifugo transport (for example via AJAX request in web application), then process it on application backend side – probably validate, save into main app database – and then `publish` into Centrifugo using HTTP API so Centrifugo broadcast message to all clients subscribed on a channel.

Server API works on `/api` endpoint. It's very simple to use: you just have to send POST request with JSON command to this endpoint.

In this chapter we will look at API protocol internals - for new API client library authors and just if you are curious how existing API clients work.

API request is a POST HTTP request with `application/json` Content-Type and JSON payload in request body.
In most cases though you can just use one of our [available HTTP API libraries](../libraries/api.md). In this chapter we will make an API method overview.

API protected by `api_key` set in Centrifugo configuration. I.e. `api_key` must be added to config, like:

Expand Down Expand Up @@ -315,7 +309,9 @@ Date: Thu, 17 May 2018 22:08:31 GMT
}
```

Keep in mind that as `channels` API command returns all active channel snapshot it can be really heavy for massive deployments. At moment there is no way to paginate over channels list and we don't know a case where this could be useful and not error prone. At moment we mostly suppose that channels command will be used in development process and in not very massive Centrifugo setups (with no more than 10k channels). Also `channels` command is considered optional in engine implementations.
**Keep in mind that since `channels` API command returns all active channels it can be really heavy for massive deployments.** At moment there is no way to paginate over channels list and we don't know a case where this could be useful and not error prone. At the moment **we mostly suppose that channels command will be used in development process and in not very massive Centrifugo setups** (with no more than 10k channels). Also `channels` command considered optional in engine implementations.

A better and scalable approach could be real-time analytics approach [described here](../pro/index.md).

### info

Expand Down
2 changes: 2 additions & 0 deletions docs/content/transports/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ At moment Centrifugo supports the following client-server transports:
Having both of these transport means that it's possible to connect to Centrifugo from everywhere.

Since Centrifugo has its own protocol for client-server communication (for authentication, subscriptions, publishing messages to channels, calling RPC etc) transports above wrapped by our [client libraries](../libraries/client.md).

Keep in mind that if you are planning to use non-JSON binary data between a client and server then you can only use WebSocket transport. See how to achieve binary passing with [protobuf](protobuf.md) format.
8 changes: 6 additions & 2 deletions docs/content/transports/sockjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ If you have a requirement to work everywhere SockJS is the solution. SockJS will
* Long-polling
* And more (see [SockJS docs](https://github.com/sockjs/sockjs-client))

One caveat when using SockJS is that **you need to use sticky sessions mechanism if you have many Centrifugo nodes running**. This mechanism usually supported by load balancers (for example Nginx). Sticky sessions mean that all requests from the same client will come to the same Centrifugo node. This is necessary because SockJS maintains connection session in process memory thus allowing bidirectional communication between a client and a server. Sticky mechanism not required if you only use one Centrifugo node on a backend. See how enable sticky sessions in Nginx in deploy section of this doc.
SockJS connection endpoint in Centrifugo is `/connection/sockjs`.

SockJS connection endpoint in Centrifugo is `/connection/sockjs`. SockJS does not support binary data, so you are limited in using JSON with it.
**There are two caveats when using SockJS**.

First is that **you need to use sticky sessions mechanism if you have many Centrifugo nodes running**. This mechanism usually supported by load balancers (for example Nginx). Sticky sessions mean that all requests from the same client will come to the same Centrifugo node. This is necessary because SockJS maintains connection session in process memory thus allowing bidirectional communication between a client and a server. Sticky mechanism not required if you only use one Centrifugo node on a backend. See how enable sticky sessions in Nginx in deploy section of this doc.

Second – **SockJS does not support binary data, so you are limited in using JSON with it**.
5 changes: 3 additions & 2 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ nav:
- Installation: 'server/install.md'
- Configuration: 'server/configuration.md'
- Console commands: 'server/commands.md'
- Client API: 'server/client_api.md'
- Server HTTP API: 'server/http_api.md'
- Server GRPC API: 'server/grpc_api.md'
- Channels: 'server/channels.md'
- Authentication: 'server/authentication.md'
- Private channels: 'server/private_channels.md'
- Engines: 'server/engines.md'
- Server HTTP API: 'server/http_api.md'
- Server GRPC API: 'server/grpc_api.md'
- Admin web interface: 'server/admin.md'
- Proxy to backend: 'server/proxy.md'
- Server-side subscriptions: 'server/server_subs.md'
Expand Down

0 comments on commit 9fce6a1

Please sign in to comment.