Skip to main content

kemal-sse

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

Informations de source

Dépôt
kemalcr/kemal
Dernière activité de la source
29 août 2026 à 16:35
Langue détectée de SKILL.md
anglais
Étoiles
3 924
Forks
206

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
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`.
Voir sur GitHub