diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index 9bb6d8d6..5c292734 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -339,6 +339,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 c260fcc6..7c6276f9 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -733,6 +733,25 @@ {::trie/trie-compiler compiler})] (dotimes [_ 10] (future - (dotimes [n 100000] - (let [body (:body (app {:request-method :get, :uri (str "/" n)}))] - (is (= body (str n)))))))))))) + (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}))))))))