Skip to main content

kemal-sse

Real-time Server-Sent Events (SSE) streaming in Kemal 1.12+, following established project patterns.

Quellinformationen

Repository
kemalcr/kemal
Letzte Quellaktivität
29. August 2026 um 16:35
Erkannte Sprache von SKILL.md
Englisch
Sterne
3.929
Forks
206

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
kemal-sse
description
Real-time Server-Sent Events (SSE) streaming in Kemal 1.12+, following established project patterns.
license
MIT
# Kemal Server-Sent Events (SSE) This skill provides expert guidance on implementing real-time unidirectional event streaming using Kemal's built-in `sse` helper (available in Kemal 1.12.0+). ## Version Notes - `sse` route helper and `Kemal::EventStream` (named events, `id:`, `retry:`): since Kemal 1.12.0. - SSE injection protection (CR/LF rejected in `event`/`id`, CRLF normalization in `data` and comments) and the `retry` field Int32 overflow fix: since Kemal 1.13.0. - Negative `retry` spans are omitted from the output (clients discard non-digit values): unreleased, after Kemal 1.13.0. ## Core Mandates - **SSE Route Definition (Kemal 1.12.0+):** Use the `sse` helper block to define an SSE endpoint: ```crystal sse "/events" do |stream, env| stream.send("hello world") end ``` - **Sending Named Events & Security:** Pass `event`, `id`, and optional `retry` (`Time::Span`) keyword arguments: ```crystal sse "/notifications" do |stream, env| stream.send({"message" => "New alert"}.to_json, event: "alert", id: 101, retry: 5.seconds) end ``` *Security Note (Kemal 1.13.0+)*: `Kemal::EventStream` prevents SSE injection by rejecting raw newlines in `event` and `id` arguments, and automatically normalizes CRLF sequences in `data` and `comment`. - **Streaming Loops & Channels:** Use Crystal channels or keep-alive loops for streaming events: ```crystal sse "/stream" do |stream, env| loop do sleep 1.seconds stream.send(Time.utc.to_s, event: "time") rescue IO::Error break # Connection closed by client end end ``` ## Patterns from Source Code ### Real-Time Live Updates with Channel / Loop ```crystal require "kemal" sse "/live-ticks" do |stream, env| count = 0_i64 loop do count += 1 stream.send( {"count" => count, "timestamp" => Time.utc.to_s}.to_json, event: "tick", id: count ) sleep 1.seconds rescue IO::Error # Client disconnected, gracefully terminate streaming loop break end end Kemal.run ``` ### Pub/Sub Broadcasting via SSE Stream Manager ```crystal require "kemal" class SseHub @streams = Array(Kemal::EventStream).new @mutex = Mutex.new def register(stream : Kemal::EventStream) @mutex.synchronize { @streams << stream } end def unregister(stream : Kemal::EventStream) @mutex.synchronize { @streams.delete(stream) } end def broadcast(data : String, event : String? = nil) @mutex.synchronize do @streams.reject! do |stream| begin stream.send(data, event: event) false rescue IO::Error true # Remove closed connections end end end end end HUB = SseHub.new sse "/subscribe" do |stream, env| HUB.register(stream) # Block while connection remains open begin sleep ensure HUB.unregister(stream) end end post "/publish" do |env| message = env.params.body["message"]? || "" HUB.broadcast(message, event: "news") env.json({status: "ok"}) end Kemal.run ``` ## Best Practices - **Connection Cleanup:** Always handle client disconnects gracefully by rescuing `IO::Error` or using an `ensure` block. - **Content Type:** Kemal automatically sets `Content-Type: text/event-stream` and `Cache-Control: no-cache` headers for SSE routes. - **JSON Serialization:** Convert Crystal data structures to JSON strings using `.to_json` before passing to `stream.send(...)`. - **API Response Helpers:** For JSON response formatting and error handling on companion HTTP routes (e.g. `post "/publish"`), follow the patterns in [`kemal-json`](../kemal-json/SKILL.md). - **Prefer SSE over WebSockets for Uni-directional Feeds:** Use SSE for live log feeds, dashboard metrics, and notifications where full bi-directional socket protocol overhead is unnecessary. ## When to Use - When building real-time dashboards, log streaming, or live notification feeds. - When client-to-server responses are handled via standard HTTP POST routes, while server-to-client updates stream via HTTP `text/event-stream`.
Auf GitHub ansehen