From 398aa8384ce6b96dadf3cf05e9a339037d20603d Mon Sep 17 00:00:00 2001 From: Francis Roberts <111994975+franrob-projects@users.noreply.github.com> Date: Wed, 22 Oct 2025 16:02:53 +0200 Subject: [PATCH] EDU-2114: Converts SSE page to MDX --- content/api/sse.textile | 187 ------------------------------ src/pages/docs/api/sse.mdx | 231 +++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 187 deletions(-) delete mode 100644 content/api/sse.textile create mode 100644 src/pages/docs/api/sse.mdx diff --git a/content/api/sse.textile b/content/api/sse.textile deleted file mode 100644 index c487ebab50..0000000000 --- a/content/api/sse.textile +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: SSE and Raw HTTP Streaming API -meta_description: "Ably provides support for Server-Sent Events (SSE). This is useful for where browser clients support SSE, and the use case does not require or support the resources used by the Ably client library SDK." -meta_keywords: "Server-Sent Events, SSE, browser clients" -section: api -index: 100 -jump_to: - API Routes: - - Server-sent events#sse - - Plain event stream#event-stream -redirect_from: - - /docs/api/versions/v1.1/sse ---- - -h3(#sse). Server-sent events - -h6. GET main.realtime.ably.net/sse - -Start a streaming HTTP request that conforms to the "Server-Sent Events":https://www.w3.org/TR/eventsource/ spec, for ease of consuming with an SSE library. - -The @/event-stream@ endpoint will give an SSE response if the @Accept@ header is set to @text/event-stream@. The @/sse@ endpoint is also provided as an easier way of forcing an SSE response. - -h5. Request parameters - -- channels := **mandatory**. One or more channel names, separated by commas (or the @separator@ if specified). Non-url-safe characters should be URL-encoded (for example, @?channels=foo%3Fbar@ will subscribe to the channel @foo?bar@). Alias: @channel@. -- v := **mandatory**. The version of the api you are requesting. The current version of the API is 1.2, so @v=1.2@ is recommended. -- separator := **optional**. A separator, to enable easy subscriptions to channels with commas in their name. For example, @?separator=|&channel=fo,o|ba,r@ will subscribe to the two channels @fo,o@ and @ba,r@. -- key := **optional**. An Ably API key to use, if using basic auth. -- accessToken := **optional** An Ably auth token to use, if using token auth. -- lastEvent := **optional**. An @id@ to resume from. Only required when starting a new SSE connection which resumes from a previous connection. -- rewind := **optional**. An integer which, if specified, will send a backlog of the number of messages specified once the connection opens. For example, @rewind=1@ will give you the most recent message sent on the channel. This is best-effort — only messages from within the last two minutes will be available, and only if the channel has been continuously active since the message was sent; it is not a replacement for the "history API":/docs/storage-history/history It only has an effect for new connections; when resuming a previous connection using @lastEvent@, it is ignored in favour of sending you the messages you missed since you were last connected. -- enveloped := **optional**. Default is @true@. If @true@, the @data@ from each event envelope for a @message@ event will be a "Message":/docs/api/realtime-sdk/types#message object. If @false@, it will be the payload from the message directly. See "Envelope format":#envelope-format below. -- heartbeats := **optional**. Default is @false@. if @true@ will use an explicit heartbeat event rather than a newline as a keepalive packet. - -h5(#envelope-format). Envelope format - -See an example of a "plain event stream":#event-stream below, except instead of a JSON object with @id@, @event@, @data@ members, you get an SSE event. - -Keepalive packets are sent as SSE comments (@:keepalive@). - -h5. Code example - -```[javascript] -var apiKey = '{{API_KEY}}'; -var url = 'https://main.realtime.ably.net/event-stream?channels=myChannel&v=1.2&key=' + apiKey; -var eventSource = new EventSource(url); - -eventSource.onmessage = function(event) { - var message = JSON.parse(event.data); - console.log('Message: ' + message.name + " - " + message.data); -}; -``` - -```[python] -import json -import sseclient - -api_key='{{API_KEY}}' -url = "https://main.realtime.ably.net/sse?channels=myChannel&v=1.2&key=%s" % (api_key) - -def with_urllib3(url): - import urllib3 - http = urllib3.PoolManager() - return http.request('GET', url, preload_content=False) - -response = with_urllib3(url) -client = sseclient.SSEClient(response) -for event in client.events(): - message = json.loads(event.data) - print("Channel: %s - Message: %s - %s " % (message['channel'], message['name'], message['data'])) -``` - -```[curl] -curl "https://main.realtime.ably.net/sse?channel=example&v=1.2" \ - --user "{{API_KEY}}" -⏎ -id: cbfKayrzgAXDWM:1556806691343-0 -event: message -data: { - "id":"YqigX7VFsR:0:0", - "name":"foo", - "timestamp":1556806691341, - "encoding":"json", - "channel":"channel", - "data":"{\"foo\":1}" -} -⏎ -:keepalive -⏎ -event: error -data:{ - "message":"Token expired. (See https://help.ably.io/error/40142 for help.)", - "code":40142, - "statusCode":401, - "href":"https://help.ably.io/error/40142" -} -``` - -h3(#event-stream). Plain HTTP event stream - -h6. GET main.realtime.ably.net/event-stream - -Starts a streaming HTTP request. This allows for messages to be easily consumed with any HTTP library that supports streaming. This is similar to the SSE endpoint, but uses JSON envelopes instead of SSE events. - -When available, we recommend using an SSE library as opposed to the raw HTTP stream as SSE libraries automatically handle reconnecting and resuming from the last received ID. - -h5. Request parameters - -- channels := **mandatory**. One or more channel names, separated by commas (or the @separator@ if specified). Non-url-safe characters should be URL-encoded (for example, @?channels=foo%3Fbar@ will subscribe to the channel @foo?bar@). Alias: @channel@. -- v := **mandatory**. The version of the api you are requesting. The current version of the API is 1.2, so @v=1.2@ is recommended. -- separator := **optional**. A separator, to enable easy subscriptions to channels with commas in their name. For example, @?separator=|&channel=fo,o|ba,r@ will subscribe to the two channels @fo,o@ and @ba,r@. -- key := **optional**. An Ably API key to use, if using basic auth. -- accessToken := **optional** An Ably auth token to use, if using token auth. -- lastEvent := **optional**. An @id@ to resume from. Only required when starting a new HTTP connection which resumes from a previous connection. -- rewind := **optional**. An integer which, if specified, will send a backlog of the number of messages specified once the connection opens. For example, @rewind=1@ will give you the most recent message sent on the channel. This is best-effort — only messages from within the last two minutes will be available, and only if the channel has been continuously active since the message was sent; it is not a replacement for the "history API":/docs/storage-history/history It only has an effect for new connections; when resuming a previous connection using @lastEvent@, it is ignored in favour of sending you the messages you missed since you were last connected. -- enveloped := **optional**. Default is @true@. If @true@, the @data@ from each event envelope for a @message@ event will be a "Message":/docs/api/realtime-sdk/types#message object. If @false@, it will be the payload from the message directly. See "Envelope format":#envelope-format below. -- heartbeats := **optional**. Default is @false@. If @true@ will use an explicit heartbeat event rather than a newline as a keepalive packet. - -h5(#envelope-format). Envelope format - -Once a streaming response is established, every line (other than empty lines sent as keepalive packets) will be a simple JSON object of the following form: - -bc[json]. { - event: , - data: , - id: -} - -If @enveloped@ is true (the default), the @data@ will be a JSON-stringified object of a type determined by the event: - -- For a @message@ event it will be a "Message":/docs/api/realtime-sdk/types#message object -- For a @presence@ event it will be a "PresenceMessage":/docs/api/realtime-sdk/types#presence-message object -- For an @error@ event it will be an "ErrorInfo":/docs/api/realtime-sdk/types#error-info object - -For a payload that is anything other than a string, as there is no client library to decode the payload of a @Message@ or @PresenceMessage@, you will have to decode it yourself. Objects and arrays will be json-encoded; binary payloads will be base64-encoded. The @encoding@ field of the @Message@ will specify what encoding has been used for the @data@ payload. - -If @enveloped@ is false, the @data@ will for a @message@ or @presence@ event be the @data@ payload from the @Message@ or @PresenceMessage@. Other events are unaffected. - -Non-string payloads will be encoded as before, but without enveloping you will not have the benefit of the @encoding@ field to tell you what encoding has been done. - -Note that failures on opening the connection (for example, invalid authentication details) may be sent as a non-streamed http response (with a response body of the form @{"error": }@), not an @error@ event in a streamed response. - -h5. Code example - -```[curl] -curl "https://main.realtime.ably.net/event-stream?channel=example&v=1.2" \ - --user "{{API_KEY}}" - -{ - "id":"cbfKayrzgAXDWM:1556804156735-0", - "event":"message", - "data":{ - "id":"oZs6XaGYx8:0:0", - "name":"message-name", - "timestamp":1556804156730, - "encoding":"json", - "channel":"example", - "data":"{\"foo\":1}" - } -} -⏎ -{ - "event":"error", - "data":{ - "message":"Token expired. (See https://help.ably.io/error/40142 for help.)", - "code":40142, - "statusCode":401, - "href":"https://help.ably.io/error/40142" - } -} -``` - -```[nodejs] -const request = require('request'); -const apiKey = '{{API_KEY}}'; -const url = 'https://main.realtime.ably.net/event-stream?channels=myChannel&v=1.2&key=' + apikey; - -request - .get(url) - .on('response', function(response) { - console.log(response.statusCode) // stream started, 200 - }) - .on('data', function(data) { - console.log('Envelope:', data.toString()) - }); -``` diff --git a/src/pages/docs/api/sse.mdx b/src/pages/docs/api/sse.mdx new file mode 100644 index 0000000000..7ab31c7bb3 --- /dev/null +++ b/src/pages/docs/api/sse.mdx @@ -0,0 +1,231 @@ +--- +title: SSE and Raw HTTP Streaming API +meta_description: "Ably provides support for Server-Sent Events (SSE). This is useful for where browser clients support SSE, and the use case does not require or support the resources used by the Ably client library SDK." +meta_keywords: "Server-Sent Events, SSE, browser clients" +jump_to: + API Routes: + - Server-sent events#sse + - Plain event stream#event-stream +redirect_from: + - /docs/api/versions/v1.1/sse +--- + +### Server-sent events + +#### GET main.realtime.ably.net/sse + +Start a streaming HTTP request that conforms to the [Server-Sent Events](https://www.w3.org/TR/eventsource/) spec, for ease of consuming with an SSE library. + +The `/event-stream` endpoint will give an SSE response if the `Accept` header is set to `text/event-stream`. The `/sse` endpoint is also provided as an easier way of forcing an SSE response. + +##### Request parameters + +| Parameter | Description | Type | +|-----------|-------------|------| +| channels | **Mandatory.** One or more channel names, separated by commas (or the `separator` if specified). Non-url-safe characters should be URL-encoded (for example, `?channels=foo%3Fbar` will subscribe to the channel `foo?bar`). Alias: `channel`. | String | +| v | **Mandatory.** The version of the api you are requesting. The current version of the API is 1.2, so `v=1.2` is recommended. | String | +| separator | **Optional.** A separator, to enable easy subscriptions to channels with commas in their name. For example, `?separator=\|&channel=fo,o\|ba,r` will subscribe to the two channels `fo,o` and `ba,r`. | String | +| key | **Optional.** An Ably API key to use, if using basic auth. | String | +| accessToken | **Optional.** An Ably auth token to use, if using token auth. | String | +| lastEvent | **Optional.** An `id` to resume from. Only required when starting a new SSE connection which resumes from a previous connection. | String | +| rewind | **Optional.** An integer which, if specified, will send a backlog of the number of messages specified once the connection opens. For example, `rewind=1` will give you the most recent message sent on the channel. This is best-effort — only messages from within the last two minutes will be available, and only if the channel has been continuously active since the message was sent; it is not a replacement for the [history API](/docs/storage-history/history) It only has an effect for new connections; when resuming a previous connection using `lastEvent`, it is ignored in favour of sending you the messages you missed since you were last connected. | Integer | +| enveloped | **Optional.** Default is `true`. If `true`, the `data` from each event envelope for a `message` event will be a [Message](/docs/api/realtime-sdk/types#message) object. If `false`, it will be the payload from the message directly. See [Envelope format](#envelope-format) below. | Boolean | +| heartbeats | **Optional.** Default is `false`. if `true` will use an explicit heartbeat event rather than a newline as a keepalive packet. | Boolean | + +##### Envelope format + +See an example of a [plain event stream](#event-stream) below, except instead of a JSON object with `id`, `event`, `data` members, you get an SSE event. + +Keepalive packets are sent as SSE comments (`:keepalive`). + +##### Code example + + + +```javascript +var apiKey = '{{API_KEY}}'; +var url = 'https://main.realtime.ably.net/event-stream?channels=myChannel&v=1.2&key=' + apiKey; +var eventSource = new EventSource(url); + +eventSource.onmessage = function(event) { + var message = JSON.parse(event.data); + console.log('Message: ' + message.name + " - " + message.data); +}; +``` + + + + + +```python +import json +import sseclient + +api_key='{{API_KEY}}' +url = "https://main.realtime.ably.net/sse?channels=myChannel&v=1.2&key=%s" % (api_key) + +def with_urllib3(url): + import urllib3 + http = urllib3.PoolManager() + return http.request('GET', url, preload_content=False) + +response = with_urllib3(url) +client = sseclient.SSEClient(response) +for event in client.events(): + message = json.loads(event.data) + print("Channel: %s - Message: %s - %s " % (message['channel'], message['name'], message['data'])) +``` + + + + +```shell +curl "https://main.realtime.ably.net/sse?channel=example&v=1.2" \ + --user "{{API_KEY}}" + +id: cbfKayrzgAXDWM:1556806691343-0 +event: message +data: { + "id":"YqigX7VFsR:0:0", + "name":"foo", + "timestamp":1556806691341, + "encoding":"json", + "channel":"channel", + "data":"{\"foo\":1}" +} + +:keepalive + +event: error +data:{ + "message":"Token expired. (See https://help.ably.io/error/40142 for help.)", + "code":40142, + "statusCode":401, + "href":"https://help.ably.io/error/40142" +} +``` + + + +### Plain HTTP event stream + +#### GET main.realtime.ably.net/event-stream + +Starts a streaming HTTP request. This allows for messages to be easily consumed with any HTTP library that supports streaming. This is similar to the SSE endpoint, but uses JSON envelopes instead of SSE events. + +When available, we recommend using an SSE library as opposed to the raw HTTP stream as SSE libraries automatically handle reconnecting and resuming from the last received ID. + +##### Request parameters + +| Parameter | Description | Type | +|-----------|-------------|------| +| channels | **Mandatory.** One or more channel names, separated by commas (or the `separator` if specified). Non-url-safe characters should be URL-encoded (for example, `?channels=foo%3Fbar` will subscribe to the channel `foo?bar`). Alias: `channel`. | String | +| v | **Mandatory.** The version of the api you are requesting. The current version of the API is 1.2, so `v=1.2` is recommended. | String | +| separator | **Optional.** A separator, to enable easy subscriptions to channels with commas in their name. For example, `?separator=\|&channel=fo,o\|ba,r` will subscribe to the two channels `fo,o` and `ba,r`. | String | +| key | **Optional.** An Ably API key to use, if using basic auth. | String | +| accessToken | **Optional.** An Ably auth token to use, if using token auth. | String | +| lastEvent | **Optional.** An `id` to resume from. Only required when starting a new HTTP connection which resumes from a previous connection. | String | +| rewind | **Optional.** An integer which, if specified, will send a backlog of the number of messages specified once the connection opens. For example, `rewind=1` will give you the most recent message sent on the channel. This is best-effort — only messages from within the last two minutes will be available, and only if the channel has been continuously active since the message was sent; it is not a replacement for the [history API](/docs/storage-history/history) It only has an effect for new connections; when resuming a previous connection using `lastEvent`, it is ignored in favour of sending you the messages you missed since you were last connected. | Integer | +| enveloped | **Optional.** Default is `true`. If `true`, the `data` from each event envelope for a `message` event will be a [Message](/docs/api/realtime-sdk/types#message) object. If `false`, it will be the payload from the message directly. See [Envelope format](#envelope-format) below. | Boolean | +| heartbeats | **Optional.** Default is `false`. If `true` will use an explicit heartbeat event rather than a newline as a keepalive packet. | Boolean | + +##### Envelope format + +Once a streaming response is established, every line (other than empty lines sent as keepalive packets) will be a simple JSON object of the following form: + + +```json +{ + event: , + data: , + id: +} +``` + + +If `enveloped` is true (the default), the `data` will be a JSON-stringified object of a type determined by the event: + +- For a `message` event it will be a [Message](/docs/api/realtime-sdk/types#message) object +- For a `presence` event it will be a [PresenceMessage](/docs/api/realtime-sdk/types#presence-message) object +- For an `error` event it will be an [ErrorInfo](/docs/api/realtime-sdk/types#error-info) object + +For a payload that is anything other than a string, as there is no client library to decode the payload of a `Message` or `PresenceMessage`, you will have to decode it yourself. Objects and arrays will be json-encoded; binary payloads will be base64-encoded. The `encoding` field of the `Message` will specify what encoding has been used for the `data` payload. + +If `enveloped` is false, the `data` will for a `message` or `presence` event be the `data` payload from the `Message` or `PresenceMessage`. Other events are unaffected. + +Non-string payloads will be encoded as before, but without enveloping you will not have the benefit of the `encoding` field to tell you what encoding has been done. + +Note that failures on opening the connection (for example, invalid authentication details) may be sent as a non-streamed http response (with a response body of the form `{"error": }`), not an `error` event in a streamed response. + +##### Code example + + +```shell +curl "https://main.realtime.ably.net/event-stream?channel=example&v=1.2" \ + --user "{{API_KEY}}" + +{ + "id":"cbfKayrzgAXDWM:1556804156735-0", + "event":"message", + "data":{ + "id":"oZs6XaGYx8:0:0", + "name":"message-name", + "timestamp":1556804156730, + "encoding":"json", + "channel":"example", + "data":"{\"foo\":1}" + } +} + +{ + "event":"error", + "data":{ + "message":"Token expired. (See https://help.ably.io/error/40142 for help.)", + "code":40142, + "statusCode":401, + "href":"https://help.ably.io/error/40142" + } +} +``` + + + + +```nodejs +const request = require('request'); +const apiKey = '{{API_KEY}}'; +const url = 'https://main.realtime.ably.net/event-stream?channels=myChannel&v=1.2&key=' + apikey; + +request + .get(url) + .on('response', function(response) { + console.log(response.statusCode) // stream started, 200 + }) + .on('data', function(data) { + console.log('Envelope:', data.toString()) + }); +``` + + + + + +```javascript +const request = require('request'); +const apiKey = '{{API_KEY}}'; +const url = 'https://main.realtime.ably.net/event-stream?channels=myChannel&v=1.2&key=' + apikey; + +request + .get(url) + .on('response', function(response) { + console.log(response.statusCode) // stream started, 200 + }) + .on('data', function(data) { + console.log('Envelope:', data.toString()) + }); +``` + + + +