Skip to content

Commit

Permalink
Preliminary support for Server-Sent Events [IMMUTANT-439]
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrossley3 committed Jan 26, 2015
1 parent 446c6c0 commit 59a9d5a
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
40 changes: 40 additions & 0 deletions web/src/immutant/web/sse.clj
@@ -0,0 +1,40 @@
;; Copyright 2014-2015 Red Hat, Inc, and individual contributors.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.

(ns immutant.web.sse
"Provides Server-Sent Events via [[immutant.web.async/as-channel]]"
(:require [immutant.web.async :as async]))

(defn with-event-type [m]
(update-in m [:headers] assoc "Content-Type" "text/event-stream; charset=utf-8"))

(def as-sse-channel (comp with-event-type async/as-channel))

(defprotocol Event
(event->str [x] "Formats event according to SSE spec"))

(extend-protocol Event
Object
(event->str [o] (str "data:" o "\n"))
java.util.Collection
(event->str [c] (apply str (map event->str c)))
java.util.Map
(event->str [m] (apply str
(-> (for [[k v] (dissoc m :data)]
(format "%s:%s\n" (name k) v))
(conj (event->str (:data m)))))))

(defn send!
[ch event]
(async/send! ch (str (event->str event) "\n")))
38 changes: 38 additions & 0 deletions web/test/immutant/web/sse_test.clj
@@ -0,0 +1,38 @@
;; Copyright 2014-2015 Red Hat, Inc, and individual contributors.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.

(ns immutant.web.sse-test
(:require [clojure.test :refer :all]
[immutant.web.sse :refer :all]
[clojure.string :refer (split-lines)]))

(deftest format-string
(is (= "data:foo\n"
(event->str "foo"))))

(deftest format-collection
(is (= "data:0\ndata:1\ndata:2\n"
(event->str [0 1 2])
(event->str (range 3))
(event->str '("0" "1" "2")))))

(deftest format-map
(let [result (event->str {:data "foo", :event "bar", :id 42, :retry 1000})
sorted (sort (split-lines result))]
(is (.endsWith result "\n"))
(is (= ["data:foo" "event:bar" "id:42" "retry:1000"] sorted))))

(deftest format-collection-in-map
(is (= "data:0\ndata:1\ndata:2\n"
(event->str {:data (range 3)}))))

0 comments on commit 59a9d5a

Please sign in to comment.