ReqServerSentEvents.Frame (ReqServerSentEvents v0.2.0)

Copy Markdown View Source

Pure SSE frame parser. No IO, no processes, no external dependencies.

An SSE frame is a sequence of field: value lines terminated by a blank line (\n\n). Recognised fields: event, data, id, retry. Lines starting with : are comments. Multiple data: lines within one frame are concatenated with "\n".

Summary

Functions

Parse one complete raw frame string (without the trailing "\n\n") into a %Frame{}.

Split a byte buffer on the SSE frame delimiter ("\n\n").

Types

t()

@type t() :: %ReqServerSentEvents.Frame{
  comments: [String.t()],
  data: String.t() | nil,
  event: String.t() | nil,
  id: String.t() | nil,
  retry: non_neg_integer() | nil
}

Functions

parse(raw)

@spec parse(binary()) :: t()

Parse one complete raw frame string (without the trailing "\n\n") into a %Frame{}.

Frames with no data: field are returned as-is — the caller decides whether to dispatch or discard them. Unknown field names are silently ignored per the SSE spec.

Examples

iex> ReqServerSentEvents.Frame.parse("event: ping\ndata: {}")
%ReqServerSentEvents.Frame{event: "ping", data: "{}"}

iex> ReqServerSentEvents.Frame.parse(": keepalive")
%ReqServerSentEvents.Frame{comments: ["keepalive"]}

split(buffer)

@spec split(binary()) :: {[binary()], binary()}

Split a byte buffer on the SSE frame delimiter ("\n\n").

"\r\n" sequences are normalised to "\n" before splitting, so servers that send CRLF line endings (e.g. "\r\n\r\n" frame delimiters) are handled transparently. The returned frame strings use "\n" throughout. A leading UTF-8 byte order mark ("\uFEFF") is stripped per the SSE spec.

Returns {complete_frames, leftover} where complete_frames is a list of raw frame strings (without the trailing "\n\n") and leftover is the remaining bytes that have not yet formed a complete frame.

Examples

iex> ReqServerSentEvents.Frame.split("data: hello\n\n")
{["data: hello"], ""}

iex> ReqServerSentEvents.Frame.split("data: hello\r\n\r\n")
{["data: hello"], ""}

iex> ReqServerSentEvents.Frame.split("data: partial")
{[], "data: partial"}