From 6d6ab43a6b9ee47f86c6e3b8e79854770f136d09 Mon Sep 17 00:00:00 2001 From: Sam Ritchie Date: Thu, 25 Sep 2014 10:52:38 -0600 Subject: [PATCH 1/3] update dependency versions --- project.clj | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/project.clj b/project.clj index 81e8de7..ffc8870 100644 --- a/project.clj +++ b/project.clj @@ -3,16 +3,14 @@ :url "http://github.com/cemerick/drawbridge" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.2.0"] - [org.clojure/tools.nrepl "0.2.0-beta5"] - [ring/ring-core "1.0.2"] - [cheshire "3.0.0"] + :dependencies [[org.clojure/clojure "1.7.0-alpha2"] + [org.clojure/tools.nrepl "0.2.5"] + [ring/ring-core "1.3.0"] + [cheshire "5.3.1"] ;; client - [clj-http "0.3.6"]] - :dev-dependencies [[ring "1.0.0"]] - :profiles {:dev {:dependencies [[ring "1.0.0"]] + [clj-http "1.0.0"]] + :profiles {:dev {:dependencies [[ring "1.3.0"]] :plugins [[lein-clojars "0.9.0"]]} - :1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} - :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}} + :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}} :main ^{:skip-aot true} cemerick.drawbridge) From 9c127c0b99fd38d076df96495fb418c19f6cc4eb Mon Sep 17 00:00:00 2001 From: Sam Ritchie Date: Thu, 25 Sep 2014 10:54:06 -0600 Subject: [PATCH 2/3] saving. --- project.clj | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/project.clj b/project.clj index ffc8870..3a12c85 100644 --- a/project.clj +++ b/project.clj @@ -1,6 +1,6 @@ -(defproject com.cemerick/drawbridge "0.0.6" +(defproject racehub/drawbridge "0.1.0" :description "HTTP transport support for Clojure's nREPL implemented as a Ring handler." - :url "http://github.com/cemerick/drawbridge" + :url "http://github.com/racehub/drawbridge" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.7.0-alpha2"] @@ -10,7 +10,6 @@ ;; client [clj-http "1.0.0"]] - :profiles {:dev {:dependencies [[ring "1.3.0"]] - :plugins [[lein-clojars "0.9.0"]]} + :profiles {:dev {:dependencies [[ring "1.3.0"]]} :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}} :main ^{:skip-aot true} cemerick.drawbridge) From d36d01d6c3eae010da8e8447e4df8aadb1176a7f Mon Sep 17 00:00:00 2001 From: Sam Ritchie Date: Sat, 3 Jan 2015 09:37:49 -0700 Subject: [PATCH 3/3] add custom in-memory session store --- README.md | 5 ++- src/cemerick/drawbridge.clj | 67 +++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 0e9dee1..0d56ff3 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ authentication or authorization to some application-specific role, those prerequisites will apply just as with any other Ring handler in the same context. -Some things to be aware of when using `cemerick.drawbridge/ring-handler`: +Some things to be aware of when using `cemerick.drawbridge/ring-handler`: * It requires `GET` and `POST` requests to be routed to whatever URI to which it is mapped; other request @@ -75,7 +75,6 @@ Some things to be aware of when using `cemerick.drawbridge/ring-handler`: * `keyword-params` * `nested-params` * `wrap-params` - * `wrap-session` Especially if you are going to be connecting to your webapp's nREPL endpoint with a client that uses Drawbridge's own HTTP/HTTPS client @@ -111,7 +110,7 @@ yet been addressed at all. ## Need Help? Send a message to the [clojure-tools](http://groups.google.com/group/clojure-tools) -mailing list, or ping `cemerick` on freenode irc or +mailing list, or ping `cemerick` on freenode irc or [twitter](http://twitter.com/cemerick) if you have questions or would like to contribute patches. diff --git a/src/cemerick/drawbridge.clj b/src/cemerick/drawbridge.clj index de4edf6..b042f80 100644 --- a/src/cemerick/drawbridge.clj +++ b/src/cemerick/drawbridge.clj @@ -8,12 +8,13 @@ (ns ^{:doc "HTTP transport support for Clojure's nREPL implemented as a Ring handler." :author "Chas Emerick"} - cemerick.drawbridge + cemerick.drawbridge (:require [clojure.tools.nrepl :as nrepl] (clojure.tools.nrepl [transport :as transport] [server :as server]) [cheshire.core :as json] [clj-http.client :as http] + [ring.middleware.session.memory :as mem] [ring.util.response :as response] clojure.walk [clojure.java.io :as io]) @@ -46,6 +47,15 @@ (def response-timeout-header "REPL-Response-Timeout") (def ^{:private true} response-timeout-header* (.toLowerCase response-timeout-header)) +(defn memory-session + "Wraps the supplied handler in session middleware that uses a + private memory store. Use the `:cookie-name` option to customize the + cookie used here. The cookie name defaults to + \"drawbridge-session\"." + [handler & {:keys [cookie-name] :or {cookie-name "drawbridge-session"}}] + (let [store (mem/memory-store)] + (wrap-session handler {:store store :cookie-name cookie-name}))) + (defn ring-handler "Returns a Ring handler implementing an HTTP transport endpoint for nREPL. @@ -55,9 +65,8 @@ * keyword-params * nested-params * wrap-params - * wrap-session - a.k.a. the Compojure \"api\" stack, plus sessions. + a.k.a. the Compojure \"api\" stack. nREPL messages should be encoded into POST request parameters; messages are only accepted from POST parameters. @@ -68,7 +77,7 @@ * the handler is created with a non-zero :default-read-timeout, or * a session's first request to the handler specifies a non-zero timeout via a REPL-Response-Timeout header - + ...then each request will wait the specified number of milliseconds for additional nREPL responses before finalizing the response. @@ -88,41 +97,41 @@ evaluation, sessions, readably-printed evaluation values, and prompting for *in* input. Please refer to the main nREPL documentation for details on semantics and message schemas for these middlewares." - [& {:keys [nrepl-handler default-read-timeout] + [& {:keys [nrepl-handler default-read-timeout cookie-name] :or {nrepl-handler (server/default-handler) - default-read-timeout 0}}] + default-read-timeout 0 + cookie-name "drawbridge-session"}}] ;; TODO heartbeat for continuous feeding mode - (fn [{:keys [params session headers request-method] :as request}] - ;(println params session) - (let [msg (clojure.walk/keywordize-keys params)] - (cond - (not (#{:post :get} request-method)) illegal-method-error - - (and (:op msg) (not= :post request-method)) message-post-error - - :else - (let [[read write :as transport] (or (::transport session) - (transport/piped-transports)) - client (or (::client session) - (nrepl/client read (if-let [timeout (get headers response-timeout-header*)] - (Long/parseLong timeout) - default-read-timeout)))] - (response transport client - (do - (when (:op msg) - (future (server/handle* msg nrepl-handler write))) - (client)))))))) + (-> (fn [{:keys [params session headers request-method] :as request}] + ;(println params session) + (let [msg (clojure.walk/keywordize-keys params)] + (cond + (not (#{:post :get} request-method)) illegal-method-error + + (and (:op msg) (not= :post request-method)) message-post-error + + :else + (let [[read write :as transport] (or (::transport session) + (transport/piped-transports)) + client (or (::client session) + (nrepl/client read (if-let [timeout (get headers response-timeout-header*)] + (Long/parseLong timeout) + default-read-timeout)))] + (response transport client + (do + (when (:op msg) + (future (server/handle* msg nrepl-handler write))) + (client))))))) + (memory-session :cookie-name cookie-name))) ;; enable easy interactive debugging of typical usage (def ^{:private true} app (-> (ring-handler) wrap-keyword-params wrap-nested-params - wrap-params - wrap-session)) + wrap-params)) ;; as an example: (defn -main [& args] (let [options (clojure.walk/keywordize-keys (apply hash-map args)) run-jetty (ns-resolve (doto 'ring.adapter.jetty require) 'run-jetty)] (run-jetty #'app (merge {:port 0} options)))) -