(with-channel ring-req ch-name & body)
Evaluates body with `ch-name` bound to the request's underlying
asynchronous HTTP or WebSocket channel, and returns {:body AsyncChannel}
as an implementation detail.
;; Asynchronous HTTP response (with optional streaming)
(defn my-async-handler [request]
(with-channel request ch ; Request's channel
;; Make ch available to whoever can deliver the response to it; ex.:
(swap! clients conj ch))) ; given (def clients (atom #{}))
;; Some place later:
(doseq [ch @clients]
(swap! clients disj ch)
(send! ch {:status 200
:headers {"Content-Type" "text/html"}
:body your-async-response}
;; false ; Uncomment to use chunk encoding for HTTP streaming
)))
;; WebSocket response
(defn my-chatroom-handler [request]
(if-not (:websocket? request)
{:status 200 :body "Welcome to the chatroom! JS client connecting..."}
(with-channel request ch
(println "New WebSocket channel:" ch)
(on-receive ch (fn [msg] (println "on-receive:" msg)))
(on-close ch (fn [status] (println "on-close:" status)))
(send! ch "First chat message!"))))
Channel API (see relevant docstrings for more info):
(open? [ch])
(close [ch])
(websocket? [ch])
(send! [ch data] [ch data close-after-send?])
(on-receieve [ch callback])
(on-close [ch callback])
See org.httpkit.timer ns for optional timeout facilities.
Source
(defmacro with-channel
"Evaluates body with `ch-name` bound to the request's underlying
asynchronous HTTP or WebSocket channel, and returns {:body AsyncChannel}
as an implementation detail.
;; Asynchronous HTTP response (with optional streaming)
(defn my-async-handler [request]
(with-channel request ch ; Request's channel
;; Make ch available to whoever can deliver the response to it; ex.:
(swap! clients conj ch))) ; given (def clients (atom #{}))
;; Some place later:
(doseq [ch @clients]
(swap! clients disj ch)
(send! ch {:status 200
:headers {\"Content-Type\" \"text/html\"}
:body your-async-response}
;; false ; Uncomment to use chunk encoding for HTTP streaming
)))
;; WebSocket response
(defn my-chatroom-handler [request]
(if-not (:websocket? request)
{:status 200 :body \"Welcome to the chatroom! JS client connecting...\"}
(with-channel request ch
(println \"New WebSocket channel:\" ch)
(on-receive ch (fn [msg] (println \"on-receive:\" msg)))
(on-close ch (fn [status] (println \"on-close:\" status)))
(send! ch \"First chat message!\"))))
Channel API (see relevant docstrings for more info):
(open? [ch])
(close [ch])
(websocket? [ch])
(send! [ch data] [ch data close-after-send?])
(on-receieve [ch callback])
(on-close [ch callback])
See org.httpkit.timer ns for optional timeout facilities."
[ring-req ch-name & body]
`(let [ring-req# ~ring-req
~ch-name (:async-channel ring-req#)]
(if (:websocket? ring-req#)
(if (send-websocket-handshake! ~ch-name ring-req#)
(do ~@body {:body ~ch-name})
{:status 400 :body "Bad Sec-WebSocket-Key header"})
(do ~@body {:body ~ch-name}))))