Ring middleware to stream Server-Sent Events (SSE) - a lightweight and standardized technology as part of HTML5 where the client receives automatic push notifications from the server via HTTP connection.
More details on W3C and Wikipedia.
Clojars coordinates [ring-sse-middleware "0.1.3"]
Requires Clojure 1.8 or higher.
No web server dependency is included. You must add a compatible web server to your project.
This middleware is tested with the following web servers:
Web server | Version |
---|---|
Aleph/Manifold | 0.4.0 to 0.4.6 |
HTTP Kit | 2.1.x to 2.5.1 |
Immutant | 2.1.9 to 2.1.10 |
Jetty adapter | 9.2.x (Ring 1.4.0) to 9.4.x (Ring 1.9.0) |
Remainder of this document uses the following namespace aliases:
(require '[ring-sse-middleware.core :as r])
(require '[ring-sse-middleware.wrapper :as w])
(require '[ring-sse-middleware.adapter.generic :as g]) ; for any server with no response buffering
(require '[ring-sse-middleware.adapter.http-kit :as h]) ; for HTTP-Kit server only
(require '[ring-sse-middleware.adapter.immutant :as i]) ; for Immutant server only
(require '[ring-sse-middleware.adapter.manifold :as m]) ; for Manifold (Aleph server) only
Let us assume you have
handler
/app/metrics
that returns a JSON string of metrics dataYou want to periodically (at 1 second interval) query this data and stream it to a browser client for visualization. Use ring-sse-middleware to set up streaming.
(def wrapped-handler (-> handler
(r/streaming-middleware h/generate-stream))) ; for Aleph it would be m/generate-stream
Once you start HTTP Kit, you can fetch the stream from the URI /app/metrics?stream=true
on the same server. The
default configuration is triggered with query parameter stream=true
for HTTP GET requests, and has 1 second interval.
Let us assume you have
handler
emit-score
that returns a comma-separated string of a cricket match scoreYou want to periodically (at 3 seconds interval) query this data at URI /score
and stream it to a remote client.
Use the ring-sse-middleware to set up streaming for at most 100 clients.
(def wrapped-handler (-> handler
(r/streaming-middleware g/generate-stream {:request-matcher (partial r/uri-match "/score")
:chunk-generator (-> (fn [_] (emit-score))
(w/wrap-delay 3000)
w/wrap-sse-event
w/wrap-pst)
:max-connections 100})))
Once you start Jetty, you can fetch the stream from the URI /score
on the server. Be sure to configure Jetty's output
buffering to minimum to instantly receive the stream updates. This example uses generic g/generate-stream
streaming
function. In theory it should work with all web servers, but in practice it works with only few, often poorly. For
proper Server-sent Events support consider one of the non-generic web servers.
Run the server (any of the following commands, press Ctrl+C to stop) in one terminal:
lein do clean, aleph run
lein do clean, http-kit run
lein do clean, immutant run
lein do clean, jetty run
Run the client (press Ctrl+C to stop) in another terminal:
curl -v "localhost:3000/?stream=true"
Copyright © 2017-2021 Shantanu Kumar
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close