server_sent_event v1.0.0 ServerSentEvent
Push updates to Web clients over HTTP or using dedicated server-push protocols.
Messages are sent in the following form, with the text/event-stream
MIME type:
data: This is the first message.
data: This is the second message, it
data: has two lines.
event: custom
data: This message has event type 'custom'.
A living standard is available from WHATWG.
The contents of a server-sent-event are:
type | The type of an event |
lines | The data contents of the event split by line |
id | Value to send in last-event-id header when reconnecting |
retry | Time to wait before retrying connection in milliseconds |
comments | Any lines from original block that were marked as comments |
Link to this section Summary
Functions
Does the event have any data lines.
This event stream format's MIME type is text/event-stream
.
Create a ServerSentEvent
struct.
Parse the next event from text stream, if present.
Parse all events from text stream.
Format an event to be sent as part of a stream
Link to this section Types
Link to this section Functions
empty?(event)
Does the event have any data lines.
An event without any data lines will not trigger any browser events.
mime_type()
mime_type() :: String.t()
mime_type() :: String.t()
This event stream format's MIME type is text/event-stream
.
new(data, opts \\ [])
Create a ServerSentEvent
struct.
Examples
iex> SSE.new("my data")
...> |> Map.get(:lines)
["my data"]
iex> SSE.new("some\r\nlines")
...> |> Map.get(:lines)
["some", "lines"]
iex> SSE.new("some\nlines")
...> |> Map.get(:lines)
["some", "lines"]
iex> SSE.new("my data", id: "45")
...> |> Map.get(:id)
"45"
iex> SSE.new("my data", retry: 45)
...> |> Map.get(:retry)
45
iex> SSE.new("my data", type: "update")
...> |> Map.get(:type)
"update"
parse(stream)
Parse the next event from text stream, if present.
Examples
In these examples this module has been aliased to SSE
.
iex> SSE.parse("data: This is the first message\n\n")
{:ok, {%SSE{lines: ["This is the first message"]}, ""}}
iex> SSE.parse("data:First whitespace character is optional\n\n")
{:ok, {%SSE{lines: ["First whitespace character is optional"]}, ""}}
iex> SSE.parse("data: This message\ndata: has two lines.\n\n")
{:ok, {%SSE{lines: ["This message", "has two lines."]}, ""}}
iex> SSE.parse("data: This is the first message\n\nrest")
{:ok, {%SSE{lines: ["This is the first message"]}, "rest"}}
iex> SSE.parse("data: This message is not complete")
{:ok, {nil, "data: This message is not complete"}}
iex> SSE.parse("This line is invalid\nit doesn't contain a colon\n")
{:error, {:malformed_line, "This line is invalid"}}
iex> SSE.parse("event: custom\ndata: This message is type custom\n\n")
{:ok, {%SSE{type: "custom", lines: ["This message is type custom"]}, ""}}
iex> SSE.parse("id: 100\ndata: This message has an id\n\n")
{:ok, {%SSE{id: "100", lines: ["This message has an id"]}, ""}}
iex> SSE.parse("retry: 5000\ndata: This message retries after 5s.\n\n")
{:ok, {%SSE{retry: 5000, lines: ["This message retries after 5s."]}, ""}}
iex> SSE.parse("retry: five thousand\ndata: retry value is not a valid integer\n\n")
{:error, {:invalid_retry_value, "five thousand"}}
iex> SSE.parse(": This is a comment\n\n")
{:ok, {%SSE{comments: ["This is a comment"]}, ""}}
iex> SSE.parse("data: data can have more :'s in it'\n\n")
{:ok, {%SSE{lines: ["data can have more :'s in it'"]}, ""}}
iex> SSE.parse("DATA: field names are case-sensitive\n\n")
{:error, {:invalid_field_name, "DATA"}}
iex> SSE.parse("unknown: what is this field?\n\n")
{:error, {:invalid_field_name, "unknown"}}
# It is possible for an event stream using `CRLF` to be split mid line delimiter.
# In this case the parser needs to clear the leading newline character.
iex> SSE.parse("data: This is the first message\r\n\r")
{:ok, {%SSE{lines: ["This is the first message"]}, ""}}
iex> SSE.parse("\ndata: This is the second message\r\n\r\n")
{:ok, {%SSE{lines: ["This is the second message"]}, ""}}
parse_all(stream)
Parse all events from text stream.
Examples
In these examples this module has been aliased to SSE
.
iex> SSE.parse_all("data: First message\n\ndata: Second\ndata: message\n\nrest")
{:ok,
{
[
%SSE{lines: ["First message"]},
%SSE{lines: ["Second", "message"]}
],
"rest"
}
}
iex> SSE.parse_all("data: This is the first message\n\n")
{:ok, {[%SSE{lines: ["This is the first message"]}], ""}}
iex> SSE.parse_all("data: This is the first message\n\nrest")
{:ok, {[%SSE{lines: ["This is the first message"]}], "rest"}}
iex> SSE.parse_all("data: This message is not complete")
{:ok, {[], "data: This message is not complete"}}
iex> SSE.parse_all("This line is invalid\nit doesn't contain a colon\n")
{:error, {:malformed_line, "This line is invalid"}}
iex> SSE.parse_all("data: This is the first message\n\nThis line is invalid\n")
{:error, {:malformed_line, "This line is invalid"}}
iex> SSE.parse_all("data: This is the first message\n\nThis line is yet to terminate")
{:ok, {[%SSE{lines: ["This is the first message"]}], "This line is yet to terminate"}}
serialize(event)
Format an event to be sent as part of a stream
serialize accepts the same arguments as new to create and serialize in one step.
NOTE: Each data/comment line must be without new line charachters.
Examples
In these examples this module has been aliased to SSE
.
iex> SSE.serialize("my data", type: "update")
"event: update\ndata: my data\n\n"
iex> %SSE{type: "greeting", lines: ["Hi,", "there"], comments: ["comment"]}
...> |> SSE.serialize()
"event: greeting\n: comment\ndata: Hi,\ndata: there\n\n"
iex> %SSE{lines: ["message with id"], id: "some-id"}
...> |> SSE.serialize()
"data: message with id\nid: some-id\n\n"
iex> %SSE{lines: ["message setting retry to 10s"], retry: 10_000}
...> |> SSE.serialize()
"data: message setting retry to 10s\nretry: 10000\n\n"