Initial sketch for a ring-router

This commit is contained in:
Tommi Reiman 2017-08-13 15:44:49 +03:00
parent a208f7df6c
commit fa37e3e198
3 changed files with 111 additions and 2 deletions

43
src/reitit/ring.cljc Normal file
View file

@ -0,0 +1,43 @@
(ns reitit.ring
(:require [reitit.core :as reitit]))
(defprotocol ExpandMiddleware
(expand-middleware [this]))
(extend-protocol ExpandMiddleware
#?(:clj clojure.lang.APersistentVector
:cljs cljs.core.PersistentVector)
(expand-middleware [[f & args]]
(fn [handler]
(apply f handler args)))
#?(:clj clojure.lang.Fn
:cljs function)
(expand-middleware [this] this)
nil
(expand-middleware [_]))
(defn compile-handler [[path {:keys [middleware handler] :as meta}]]
(when-not handler
(throw (ex-info
(str "path '" path "' doesn't have a :handler defined")
{:path path, :meta meta})))
(let [wrap (->> middleware
(keep identity)
(map expand-middleware)
(apply comp identity))]
(wrap handler)))
(defn router [data]
(reitit/router data {:compile compile-handler}))
(defn ring-handler [router]
(fn
([request]
(if-let [match (reitit/match-by-path router (:uri request))]
((:handler match) request)))
([request respond raise]
(if-let [match (reitit/match-by-path router (:uri request))]
((:handler match) request respond raise)))))

View file

@ -0,0 +1,64 @@
(ns reitit.ring-test
(:require [clojure.test :refer [deftest testing is are]]
[reitit.core :as reitit]
[reitit.ring :as ring])
#?(:clj
(:import (clojure.lang ExceptionInfo))))
(defn mw [handler name]
(fn
([request]
(-> request
(update ::mw (fnil conj []) name)
(handler)
(update :body (fnil conj []) name)))
([request respond raise]
(handler
(update request ::mw (fnil conj []) name)
#(respond (update % :body (fnil conj []) name))
raise))))
(deftest ring-test
(testing "all paths should have a handler"
(is (thrown-with-msg?
ExceptionInfo
#"^path '/ping' doesn't have a :handler defined$"
(ring/router ["/ping"]))))
(testing "ring-handler"
(let [api-mw #(mw % :api)
handler (fn handle
([{:keys [::mw]}]
{:status 200 :body (conj mw :ok)})
([request respond raise]
(respond (handle request))))
app (ring/ring-handler
(ring/router
[["/ping" handler]
["/api" {:middleware [api-mw]}
["/ping" handler]
["/admin" {:middleware [[mw :admin]]}
["/ping" handler]]]]))]
(testing "normal handler"
(is (= {:status 200, :body [:ok]}
(app {:uri "/ping"}))))
(testing "with middleware"
(is (= {:status 200, :body [:api :ok :api]}
(app {:uri "/api/ping"}))))
(testing "with nested middleware"
(is (= {:status 200, :body [:api :admin :ok :admin :api]}
(app {:uri "/api/admin/ping"}))))
(testing "not found"
(is (= nil (app {:uri "/favicon.ico"}))))
(testing "3-arity"
(let [result (atom nil)
respond (partial reset! result), raise ::not-called]
(app {:uri "/api/admin/ping"} respond raise)
(is (= {:status 200, :body [:api :admin :ok :admin :api]}
@result)))))))

View file

@ -1,7 +1,9 @@
(ns reitit.doo-runner (ns reitit.doo-runner
(:require [doo.runner :refer-macros [doo-tests]] (:require [doo.runner :refer-macros [doo-tests]]
reitit.core-test)) reitit.core-test
reitit.ring-test))
(enable-console-print!) (enable-console-print!)
(doo-tests 'reitit.core-test) (doo-tests 'reitit.core-test
'reitit.ring-test)