github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/docs/realtime.md (about) 1 [Table of contents](README.md#table-of-contents) 2 3 # Realtime 4 5 The stack offers a way for applications to be notified in real-time of what 6 happens on the server via a websocket connection. 7 8 We start with a normal websocket handshake. 9 10 Websockets include a protocol description in handshake, the protocol described 11 below is hereby named `io.cozy.websocket`. 12 13 Changes to the websocket protocol should be given versions, support for older 14 version should be maintained when reasonable. 15 16 ```http 17 GET /realtime/ HTTP/1.1 18 Host: mycozy.example.com 19 Upgrade: websocket 20 Connection: Upgrade 21 Origin: http://calendar.mycozy.example.com 22 Sec-WebSocket-Key: x3JrandomLkh9GBhXDw== 23 Sec-WebSocket-Protocol: io.cozy.websocket 24 Sec-WebSocket-Version: 13 25 ``` 26 27 Then messages are sent using json: 28 29 ``` 30 client > {"method": "AUTH", 31 "payload": "xxAppOrAuthTokenxx="} 32 client > {"method": "SUBSCRIBE", 33 "payload": {"type": "io.cozy.files"}} 34 client > {"method": "SUBSCRIBE", 35 "payload": {"type": "io.cozy.contacts"}} 36 server > {"event": "UPDATED", 37 "payload": {"id": "idA", "rev": "2-705...", "type": "io.cozy.contacts", "doc": {embeded doc ...}}} 38 server > {"event": "DELETED", 39 "payload": {"id": "idA", "rev": "3-541...", "type": "io.cozy.contacts"}} 40 client > {"method": "UNSUBSCRIBE", 41 "payload": {"type": "io.cozy.contacts"}} 42 server > {"event": "UPDATED", 43 "payload": {"id": "idB", "rev": "6-457...", "type": "io.cozy.files", "doc": {embeded doc ...}}} 44 ``` 45 46 ## AUTH 47 48 It must be the first command to be sent. The client gives its token with this 49 command, and the stack will use it to know which are the permissions of the app. 50 51 ``` 52 {"method": "AUTH", "payload": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhcHAiLCJpYXQiOjE0OTg4MTY1OTEsImlzcyI6ImNvenkudG9vbHM6ODA4MCIsInN1YiI6Im1pbmkifQ.eH9DhoHz7rg8gR7noAiKfeo8eL3Q_PzyuskO_x3T8Hlh9q_IV-4zqoGtjTiO7luD6_VcLboEU-6o3XBek84VTg"} 53 ``` 54 55 ## SUBSCRIBE 56 57 A client can send a SUBSCRIBE request to be notified of changes. The payload is 58 a selector for the events it wishes to receive For now the only possible 59 selector is on type & optionally id. 60 61 ``` 62 {"method": "SUBSCRIBE", "payload": {"type": "[desired doctype]"}} 63 {"method": "SUBSCRIBE", "payload": {"type": "[desired doctype]", "id": "idA"}} 64 ``` 65 66 In order to subscribe, a client must have permission `GET` on the passed 67 selector. Otherwise an error is passed in the message feed. 68 69 ``` 70 server > {"event": "error", 71 "payload": { 72 "status": "403 Forbidden" 73 "code": "forbidden" 74 "title":"The Application can't subscribe to io.cozy.files" 75 "source": {"method": "SUBSCRIBE", "payload": {"type":"io.cozy.files"} } 76 }} 77 ``` 78 79 ## UNSUBSCRIBE 80 81 A client can send an UNSUBSCRIBE request to no longer be notified of changes 82 from a previous request. 83 84 ``` 85 {"method": "UNSUBSCRIBE", "payload": {"type": "[desired doctype]"}} 86 {"method": "UNSUBSCRIBE", "payload": {"type": "[desired doctype]", "id": "idA"}} 87 ``` 88 89 ## Response messages 90 91 A message sent by the server after a subscribe will be a JSON object with two 92 keys at root: `event` and `payload`. `event` will be one of `CREATED`, 93 `UPDATED`, `DELETED` (when a document is written in CouchDB), `NOTIFIED` (see 94 below), or `error`. The `payload` will be a map with `type`, `id`, and `doc`. 95 The `payload` can also contain an optional `old` with the old values for the 96 document in case of `UPDATED` or `DELETED`. 97 98 ## Synthetic types 99 100 The stack an inject some synthetic events for documents that are not persisted 101 in CouchDB like classical doctypes: 102 103 - [Auth confirmations](https://docs.cozy.io/en/cozy-stack/auth/#real-time-via-websockets) 104 - [Initial sync for sharings](https://docs.cozy.io/en/cozy-stack/sharing/#real-time-via-websockets) 105 - [Thumbnails for files](https://docs.cozy.io/en/cozy-stack/files/#real-time-via-websockets) 106 - [Telepointers for notes](https://docs.cozy.io/en/cozy-stack/notes/#real-time-via-websockets) 107 108 ## `POST /realtime/:doctype/:id` 109 110 This route can be used to send documents in the real-time without having to 111 persist them in CouchDB (and they can't be used for triggers). 112 113 A permission on POST for the document `:doctype/:id` is required to use this 114 endpoint. 115 116 ### Request 117 118 ```http 119 POST /realtime/io.cozy.jobs/2c577f00-145a-0138-f569-543d7eb8149c HTTP/1.1 120 Content-Type: application/json 121 ``` 122 123 ```json 124 { 125 "subtype": "progress", 126 "imported": 10, 127 "total": 42 128 } 129 ``` 130 131 ### Response 132 133 ```http 134 HTTP/1.1 204 No Content 135 ``` 136 137 ### Websocket 138 139 ``` 140 server > {"event": "NOTIFIED", 141 "payload": {"id": "2c577f00-145a-0138-f569-543d7eb8149c", 142 "type": "io.cozy.jobs", 143 "doc": {"subtype": "progress", 144 "imported": 10, 145 "total": 42}}} 146 ```