From 3fd20f229413ae81a7533c87e564d1a56700b506 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sun, 22 Jan 2023 14:15:08 +0200 Subject: [PATCH] reloading-ring-handler --- modules/reitit-ring/src/reitit/ring.cljc | 16 ++++++++++++++++ test/cljc/reitit/ring_test.cljc | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index 97fdc9d2..8cbc36d2 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -340,6 +340,22 @@ nil))) {::r/router router})))) +(defn reloading-ring-handler + "Returns a ring-handler that recreates the actual ring-handler for each request. + Takes a 0-arity function that should return a valid ring-handler. Effectively creates + an auto-reloading ring-handler, which is good for REPL-driven development. + + Example: + + ;; for dev-mode, recreate the ring-handler for each request, for prod, just once + (let [dev-mode ... + f (fn [] (reitit.ring/ring-handler ...)] + (if dev-mode (reitit.ring/reloading-ring-handler f) (f)))" + [f] + (fn + ([request] ((f) request)) + ([request respond raise] ((f) request respond raise)))) + (defn get-router [handler] (-> handler meta ::r/router)) diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index efd91884..352def12 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -736,3 +736,22 @@ (dotimes [n 100000] (let [body (:body (app {:request-method :get, :uri (str "/" n)}))] (is (= body (str n)))))))))))) + +(declare routes) + +(deftest reloading-ring-handler-test + (let [r (fn [body] {:status 200, :body body})] + (def routes ["/" (constantly (r "1"))]) ;; initial value + + (let [create-handler (fn [] (ring/ring-handler (ring/router routes)))] + (testing "static ring handler does not see underlying route changes" + (let [app (create-handler)] + (is (= (r "1") (app {:uri "/", :request-method :get}))) + (def routes ["/" (constantly (r "2"))]) ;; redefine + (is (= (r "1") (app {:uri "/", :request-method :get}))))) + + (testing "reloading ring handler sees underlying route changes" + (let [app (ring/reloading-ring-handler create-handler)] + (is (= (r "2") (app {:uri "/", :request-method :get}))) + (def routes ["/" (constantly (r "3"))]) ;; redefine again + (is (= (r "3") (app {:uri "/", :request-method :get}))))))))