Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine websockets and http to create a REST API that keeps data up to date? [closed]

I am thinking about buildning a REST API with both websockets and http where I use websockets to tell the client that new data is available or provide the new data to the client directly.

Here are some different ideas of how it could work:
ws = websocket

Idea A:

  1. David get all users with GET /users
  2. Jacob add a user with POST /users
  3. A ws message is sent to all clients with info that a new user exist
  4. David recive a message by ws and calls GET /users

Idea B:

  1. David get all users with GET /users
  2. David register to get ws updates when a change is done to /users
  3. Jacob add a user with POST /users
  4. The new user is sent to David by ws

Idea C:

  1. David get all users with GET /users
  2. David register to get ws updates when a change is done to /users
  3. Jacob add a user with POST /users and it gets the id 4
  4. David receive the id 4 of the new user by ws
  5. David get the new user with GET /users/4

Idea D:

  1. David get all users with GET /users
  2. David register to get ws updates when changes is done to /users.
  3. Jacob add a user with POST /users
  4. David receive a ws message that changes is done to /users
  5. David get only the delta by calling GET /users?lastcall='time of step one'

Which alternative is the best and what are the pros and cons?
Is it another better 'Idea E'?
Do we even need to use REST or is ws enought for all data?

Edit
To solve problems with data getting out of sync we could provide the header
"If-Unmodified-Since"
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Unmodified-Since
or "E-Tag"
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
or both with PUT requests.

like image 900
David Berg Avatar asked Oct 29 '15 21:10

David Berg


People also ask

Can I use WebSocket with REST API?

Yes. You can use REST over WebSocket with library like SwaggerSocket.

How do WebSockets maintain compatibility with HTTP?

WebSocket solves a few issues with HTTP: Bi-directional protocol — either client/server can send a message to the other party (In HTTP, the request is always initiated by the client and the response is processed by the server — making HTTP a uni-directional protocol)

Can I use WebSockets and HTTP?

WebSocket uses HTTP as the initial transport mechanism, but keeps the TCP connection alive after the HTTP response is received so that it can be used for sending messages between client and server.

Can WebSocket and HTTP on same port?

Yes it can run on the same port, in fact it must run on the same port; the raison d'etre of websocket handshake is so that the websocket can run on the same connection without confusing intermediaries that doesn't understand websocket.


2 Answers

Idea B is for me the best, because the client specifically subscribes for changes in a resource, and gets the incremental updates from that moment.

Do we even need to use REST or is ws enought for all data?

Please check: WebSocket/REST: Client connections?

like image 191
vtortola Avatar answered Sep 27 '22 20:09

vtortola


I don't know Java, but I worked with both Ruby and C on these designs...

Funny enough, I think the easiest solution is to use JSON, where the REST API simply adds the method data (i.e. method: "POST") to the JSON and forwards the request to the same handler the Websocket uses.

The underlying API's response (the response from the API handling JSON requests) can be translated to any format you need, such as HTML rendering... though I would consider simply returning JSON for most use cases.

This helps encapsulate the code and keep it DRY while accessing the same API using both REST and Websockets.

As you might infer, this design makes testing easier, since the underlying API that handles the JSON can be tested locally without the need to emulate a server.

Good Luck!

P.S. (Pub/Sub)

As for the Pub/Sub, I find it best to have a "hook" for any update API calls (a callback) and a separate Pub/Sub module that handles these things.

I also find it more resource friendly to write the whole data to the Pub/Sub service (option B) instead of just a reference number (option C) or an "update available" message (options A and D).

In general, I also believe that sending the whole user list isn't effective for larger systems. Unless you have 10-15 users, the database call might be a bust. Consider the Amazon admin calling for a list of all users... Brrr....

Instead, I would consider dividing this to pages, say 10-50 users a page. These tables can be filled using multiple requests (Websocket / REST, doesn't matter) and easily updated using live Pub/Sub messages or reloaded if a connection was lost and reestablished.

EDIT (REST vs. Websockets)

As For REST vs. Websockets... I find the question of need is mostly a subset of the question "who's the client?"...

However, once the logic is separated from the transport layer, than supporting both is very easy and often it makes more sense to support both.

I should note that Websockets often have a slight edge when it comes to authentication (credentials are exchanged once per connection instead of once per request). I don't know if this is a concern.

For the same reason (as well as others), Websockets usually have an edge with regards to performance... how big an edge over REST depends on the REST transport layer (HTTP/1.1, HTTP/2, etc').

Usually these things are negligible when it comes time to offer a public API access point and I believe implementing both is probably the way to go for now.

like image 31
Myst Avatar answered Sep 27 '22 20:09

Myst