Skip to content

Commit

Permalink
Introduce an SSE example
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrossley3 committed Jan 27, 2015
1 parent 60a2e23 commit 84a821b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
3 changes: 2 additions & 1 deletion resources/public/index.html
Expand Up @@ -10,7 +10,8 @@ <h2>Feature Demo</h2>
<ul>
<li><a href="counter">/counter</a> (demonstrates sessions)</li>
<li><a href="any/url?foo=bar&x=42">/any/url?foo=bar&x=42</a> (dumps the request map)</li>
<li><a href="websocket.html">/websocket.html</a></li>
<li><a href="websocket.html">WebSockets</a></li>
<li><a href="sse.html">Server-Sent Events</a></li>
</ul>
</body>
</html>
29 changes: 29 additions & 0 deletions resources/public/sse.html
@@ -0,0 +1,29 @@
<html>
<body>
<script>
function setupEventSource() {
var output = document.getElementById("output");
if (typeof(EventSource) !== "undefined") {
var source = new EventSource("sse");
source.onmessage = function(event) {
output.innerHTML += event.data + "<br>";
};
source.addEventListener('close', function(event) {
output.innerHTML += event.data + "<hr/>";
source.close();
}, false);
} else {
output.innerHTML = "Sorry, Server-Sent Events are not supported in your browser";
}
return false;
}
</script>

<h2>Server-Sent Events</h2>
<div>
<input type="button" id="sendID" value="Start" onclick="setupEventSource()"/>
</div>
<hr/>
<div id="output"></div>
</body>
</html>
39 changes: 27 additions & 12 deletions src/demo/web.clj
@@ -1,7 +1,8 @@
(ns demo.web
(:require [immutant.web :as web]
[immutant.web.async :as async]
[immutant.web.middleware :as web-middleware]
[immutant.web.sse :as sse]
[immutant.web.middleware :as immutant]
[compojure.route :as route]
[compojure.core :refer (ANY GET defroutes)]
[ring.util.response :refer (response redirect content-type)]
Expand All @@ -23,6 +24,29 @@
(-> (response (str "You accessed this page " count " times\n"))
(assoc :session session))))

(defn sse-countdown
[request]
(sse/as-sse-channel request
{:on-open (fn [ch]
(doseq [x (range 5 0 -1)]
(sse/send! ch x)
(Thread/sleep 500))
;; Signal the client to call EventSource.close()
(sse/send! ch {:event "close", :data "bye!"})
;; The above won't actually close the channel, so we
;; introduce a race condition by explicitly closing it
;; below. If the channel closes before the EventSource
;; closes, it'll reconnect and we do it all over again!
(.close ch))
:on-close (fn [& _] (println "SSE channel closed"))}))

(defroutes routes
(GET "/" {c :context} (redirect (str c "/index.html")))
(GET "/counter" [] counter)
(GET "/sse" [] sse-countdown)
(route/resources "/")
(ANY "*" [] echo))

(def websocket-callbacks
"WebSocket callback functions"
{:on-open (fn [channel]
Expand All @@ -32,19 +56,10 @@
:on-message (fn [ch m]
(async/send! ch (apply str (reverse m))))})

(defroutes routes
(GET "/" {c :context :as request}
(if (:websocket? request)
(async/as-channel request
websocket-callbacks)
(redirect (str c "/index.html"))))
(GET "/counter" [] counter)
(route/resources "/")
(ANY "*" [] echo))

(defn -main [& {:as args}]
(web/run
(-> routes
(web-middleware/wrap-session {:timeout 20}))
(immutant/wrap-session {:timeout 20})
(immutant/wrap-websocket websocket-callbacks))
(merge {"host" (env :demo-web-host), "port" (env :demo-web-port)}
args)))

0 comments on commit 84a821b

Please sign in to comment.