66
77(ns gorilla-repl.websocket-relay
88 (:require [org.httpkit.server :as server]
9+ [clojure.tools.nrepl.server :as nrepl-server]
910 [clojure.tools.nrepl :as nrepl]
11+ [clojure.tools.nrepl [transport :as transport]]
12+ [gorilla-repl.render-values-mw :as render-mw] ; ; it's essential this import comes after the previous one!
13+ [cider.nrepl :as cider]
14+ [ring.middleware.session :as session]
15+ [ring.middleware.session.memory :as mem]
1016 [cheshire.core :as json]))
1117
1218; ; We will open a single connection to the nREPL server for the life of the application. It will be stored here.
2026 (let [new-conn (nrepl/connect :port port)]
2127 (swap! conn (fn [x] new-conn))))
2228
23- (defn- send-json-over-ws
24- [channel data]
25- (let [json-data (json/generate-string data)]
26- #_(println json-data)
27- (server/send! channel json-data)))
29+ (def ^:private nrepl-handler (apply nrepl-server/default-handler
30+ (-> (map resolve cider/cider-middleware)
31+ (conj #'render-mw/render-values))))
32+
33+ (defn- process-replies
34+ [reply-fn replies]
35+ (doall (->> replies
36+ (map reply-fn))))
2837
29- (defn- process-message
38+ (defn- process-message-net
3039 [channel data]
3140 (let [parsed-message (assoc (json/parse-string data true ) :as-html 1 )
3241 client (nrepl/client @conn Long/MAX_VALUE)
3342 replies (nrepl/message client parsed-message)]
3443 ; ; send the messages out over the WS connection one-by-one.
35- (doall (map (partial send-json-over-ws channel) replies))))
36-
37- (defn ring-handler
38- " This ring handler expects the client to make a websocket connection to the endpoint. It relays messages back and
39- forth to an nREPL server. A connection to the nREPL server must have previously been made with 'connect-to-nrepl'.
40- Messages are mapped back and forth to JSON as they pass through the relay."
41- [request]
42- (server/with-channel
43- request
44- channel
45- (server/on-receive channel (partial process-message channel))))
44+ (let [reply-fn (partial process-replies
45+ #(server/send!
46+ channel
47+ {:body (json/generate-string %)}))]
48+ (reply-fn replies))))
49+
50+ (defn- process-message-mem
51+ [transport channel timeout data]
52+ (let [msg (assoc (json/parse-string data true ) :as-html 1 )
53+ [read write] transport
54+ client (nrepl/client read timeout)]
55+ ((partial process-replies #(server/send!
56+ channel
57+ {:body (json/generate-string %)
58+ :session {::tranport transport}}))
59+ (do
60+ (when (:op msg)
61+ (future (nrepl-server/handle* msg nrepl-handler write)))
62+ (client )))))
63+
64+ (defn- memory-session
65+ " Wraps the supplied handler in session middleware that uses a
66+ private memory store."
67+ [handler]
68+ (let [store (mem/memory-store )]
69+ (session/wrap-session handler {:store store :cookie-name " gorilla-session" })))
70+
71+
72+ (defn on-receive-net
73+ " Relays messages back and forth to an nREPL server. A connection to the nREPL server must have
74+ previously been made with 'connect-to-nrepl'."
75+ [_ channel]
76+ (partial process-message-net channel))
77+
78+ (defn on-receive-mem
79+ " Passes messages into nREPL (in memory)"
80+ [request channel]
81+ (let [session (:session request)
82+ transport (or (::transport session)
83+ (transport/piped-transports ))]
84+ (partial process-message-mem transport channel 1000 )))
85+
86+ (defn repl-ring-handler
87+ " Creates a websocket ring handler for nrepl messages. Messages are mapped back and forth to JSON."
88+ [on-receive-fn]
89+ (-> (fn [request]
90+ (server/with-channel
91+ request
92+ channel
93+ (server/on-receive channel (on-receive-fn request channel))))
94+ (memory-session )))
0 commit comments