Streaming Events
The Lookout Mobile Risk API version 2 uses Server-Sent Events’ (SSE) protocol to push data to clients that ‘subscribe’ to the /events
endpoint. The publishing model formats Lookout data in the Event stream as described by the server-sent events protocol.
Server Sent Events are useful in our case because the listener opens a unidirectional channel that does not require any client resources other than listening for events and handling them as they arrive
To subscribe to an event stream, create an EventSource object and pass it the URL of your stream:
} |
If the URL passed to the EventSource constructor is an absolute URL, its origin (scheme, domain, port) must match that of the calling page.
Event Stream Format
The event stream from the source is a plaintext response, served with a
text/event-stream Content-Type
, that follows the SSE format. In its basic form, the response contains a data: line, followed by the event message, followed by two "\n" characters to end the stream:
data: Event message\n\n
Multiline Data
The server breaks longer messages using multiple data: lines. Two or more consecutive lines beginning with data: are considered a single piece of data, meaning only one message event will be fired. Each line ends in a single "\n" (except for the last, which ends with two "\n" characters . The result passed to your message handler is a single string concatenated by newline characters. For example:
data: first line\n
data: second line\n\n
Streaming Mobile Risk Device, Threat, and Audit events
The streaming format for mobile risk device, issue, and audit events is straightforward. The /Events endpoint streams mobile risk device, threat and audit events from the endpoint.
The protocol uses the text/event-stream Content-Type and messages of the form:
< HTTP/1.1 200 OK
< Server: nginx
< Date: Fri, 26 Jul 2024 22:19:31 GMT
< Content-Type: text/event-stream
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache
< X-Accel-Buffering: no
< Strict-Transport-Security: max-age=31536000
<
event:heartbeat
data:{}
event:heartbeat
data:{}
event:heartbeat
data:{}
id:0190ec04-a5f0-731e-bb68-a9b89d37669f
event:events
data:{"events":[{"id":"0190cd04-9520-7120-8a5e-a8866b8eca40","enterprise_guid":"680d9d84-ad0e-4706-b008-09e358df72b4","created_time":"2024-07-19T22:02:28.539+00:00","type":"AUDIT","change_type":"CREATED","audit":{"type":"CLASSIFICATION_POLICY","attribute_changes":[{"name":"agent_outdated"},{"name":"severity","from":"medium","to":"high"},{"name":"override_properties","to":"[\"minimumCompliantVersion\"]"},{"name":"policy_group_name"} ...
Each event is separated by two empty lines (\n) and can include various optional fields.
The event field specifies event types:
Event Type | Description |
---|---|
event | The event type signals a data field follows containing one or more events. |
reconnect | A reconnect event type signals that the channel is shutting down. Clients should reconnect. |
heartbeat | The server sends a heartbeat event every 5 seconds. Clients that determine the heartbeat event has stopped should disconnect and then reconnect using the last id processed to get events from that id onwards. |
end | This event type indicates the server has shut down the stream (for example, to switch to a different server). Clients receiving this event can open a new connection (using the same URL). |
The data field contains an array of events in the payload. Each event has an UUIDv7 format id field that uniquely identifies and incorporates a time component, making them sortable.
The data field events:
Data Field Elements | Description |
---|---|
Event ID | The id field in a message contains the id of the last event in the array in data. If the client needs to reconnect, it can use the last id it processed as the id parameter in the request, or the last-event-id header to start the event fetch after the last processed id. If the server closes or drops the connection, the client can reconnect with the last id processed to get events from that id and forward. |
Event |
An event descriptor as defined in the swagger models section. For example:
|