depasqualeorg/swift-sse
Swift SSE is a minimal parser for Server-Sent Events streams.
Installation
Add the package dependency:
dependencies: [
.package(url: "https://github.com/DePasqualeOrg/swift-sse.git", from: "0.1.0")
]Then add the product to your target:
dependencies: [
.product(name: "SSE", package: "swift-sse")
]Usage
Parse a buffered response body
import SSE
let events = Parser.parse(data)
for event in events {
print(event.eventType)
print(event.data)
}Choosing an API
Use the event-only APIs when you only care about dispatched SSE events:
Parser.parse(_:)parser.nextEvent()byteStream.events
These surfaces filter out terminated SSE blocks that only update parser state, such as:
id\n\nretry: 3000\n\n
Use the block-aware APIs when you need to observe those state-only updates:
Parser.parseBlocks(_:)parser.nextBlock()byteStream.sseBlocks
This matters for clients that need to react to:
Last-Event-IDchanges even when no event was dispatchedretry:updates even when no event was dispatched
Parse state-aware SSE blocks
import SSE
for block in Parser.parseBlocks(data) {
if let event = block.dispatchedEvent {
print(event.data)
} else if let retry = block.retry {
print("retry:", retry)
} else if let id = block.id {
print("last-event-id:", block.lastEventId)
print("raw id field:", id)
}
}Parse incrementally
import SSE
var parser = Parser()
for byte in bytes {
parser.consume(byte)
while let event = parser.nextEvent() {
print(event.data)
}
}
parser.finish()Parse an async byte stream
import SSE
for try await event in byteStream.events {
print(event.eventType)
print(event.data)
}Parse an async byte stream with control updates
import SSE
for try await block in byteStream.sseBlocks {
if let retry = block.retry {
updateRetryDelay(milliseconds: retry)
}
if let event = block.dispatchedEvent {
handleEvent(event)
}
}API Overview
ServerSentEvent
Represents a dispatched SSE event.
Property | Meaning --- | --- id | The raw id: field from this event block, or nil if the block omitted id: event | The raw custom event type from event:, or nil when the default "message" type applies eventType | The effective event type, defaulting to "message" data | The dispatched payload. This is always present on ServerSentEvent retry | The valid retry: value from this same block, if present lastEventId | The committed stream-level Last-Event-ID value after this event was processed
Important distinctions:
idis event-locallastEventIdis stream-level committed stateid == ""is valid and means the stream ID was reset
ServerSentEventBlock
Represents the observable result of a terminated SSE block, including blocks that did not dispatch an event.
Property | Meaning --- | --- id | The raw id: field from this block, if present event | The raw custom event type from this block, if present data | The dispatched payload, or nil if this block did not dispatch an event retry | The valid retry: value from this block, if present lastEventId | The committed stream-level Last-Event-ID value after this block was processed reconnectionTime | The current stream-level reconnection time after this block was processed dispatchedEvent | A ServerSentEvent view of this block when data is non-nil
Important distinctions:
data == nilmeans no event was dispatcheddata == ""means an event was dispatched with an empty payload
ServerSentEventsParser
Incremental parser state.
API | Meaning --- | --- consume(:) | Feed one byte into the parser consume( bytes:) | Feed a sequence of bytes into the parser finish() | Signal end-of-stream; incomplete trailing events are discarded per the SSE spec nextBlock() | Pop the next parsed ServerSentEventBlock nextEvent() | Pop the next dispatched ServerSentEvent, filtering out state-only blocks parseBlocks(:) | Parse a complete buffered byte sequence into blocks parse(:) | Parse a complete buffered byte sequence into dispatched events only lastEventId | Current committed stream-level Last-Event-ID reconnectionTime | Current stream-level reconnection time from retry:
Async parsing
API | Meaning --- | --- byteStream.sseBlocks | Async block-aware parsing surface byteStream.events | Async event-only parsing surface
Behavior notes:
- upstream async sequence failures are rethrown
- EOF does not dispatch an incomplete trailing event
.eventsfilters out state-only blocks
Short aliases
The package also exposes these shorthand aliases:
EventforServerSentEventBlockforServerSentEventBlockParserforServerSentEventsParser
Scope
This package is intentionally parser-only.
Out of scope:
- opening HTTP connections
- reconnect scheduling
readyStateor DOM-style event handlers- a full
EventSourceclient abstraction
Those concerns should stay in the consuming transport/client library.
Package Metadata
Repository: depasqualeorg/swift-sse
Default branch: main
README: README.md