/
server.clj
43 lines (36 loc) · 1.38 KB
/
server.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
(ns adzerk.boot-reload.server
(:require
[clojure.java.io :as io]
[boot.util :as util]
[org.httpkit.server :as http]
[clojure.string :as string])
(:import
[java.io IOException]
[java.net URI]))
(def state (atom {}))
(defn web-path [proto rel-path tgt-path asset-path]
(if-not (= "file:" proto)
(if asset-path
(string/replace rel-path (re-pattern (str "^" asset-path "/")) "")
(str "/" rel-path))
(.getCanonicalPath (io/file tgt-path rel-path))))
(defn send-changed! [tgt-path asset-path changed]
(doseq [[id {:keys [proto channel]}] @state]
(http/send! channel
(pr-str (into [] (map #(web-path proto % tgt-path asset-path) changed))))))
(defn set-proto! [channel proto]
(doseq [[id {c :channel}] @state]
(when (= c channel) (swap! state assoc-in [id :proto] proto))))
(defn connect! [channel]
(let [id (gensym)]
(swap! state assoc id {:channel channel})
(http/on-close channel (fn [_] (swap! state dissoc id)))
(http/on-receive channel #(set-proto! channel (read-string %)))))
(defn handler [request]
(if-not (:websocket? request)
{:status 501 :body "Websocket connections only."}
(http/with-channel request channel (connect! channel))))
(defn start
[{:keys [ip port] :as opts}]
(let [o {:ip (or ip "0.0.0.0") :port (or port 0)}]
(assoc o :port (-> (http/run-server handler o) meta :local-port))))