Reitit is a fast data-driven router for Clojure(Script).
- Simple data-driven route syntax
- Route conflict resolution
- First-class route data
- Bi-directional routing
- Pluggable coercion (schema, clojure.spec, malli)
- Helpers for ring, http, pedestal & frontend
- Friendly Error Messages
- Extendable
- Modular
- Fast
There is #reitit in Clojurians Slack for discussion & help.
reitit
- all bundledreitit-core
- the routing corereitit-ring
- a ring routerreitit-middleware
- common middleware forreitit-ring
reitit-spec
clojure.spec coercionreitit-schema
Schema coercionreitit-swagger
Swagger2 apidocsreitit-swagger-ui
Integrated Swagger UI.reitit-frontend
Tools for frontend routingreitit-http
http-routing with Pedestal-style Interceptorsreitit-interceptors
- common interceptors forreitit-http
reitit-sieppari
support for Sieppari Interceptorsreitit-dev
- development utilities
reitit-pedestal
support for Pedestal
All bundled:
[metosin/reitit "0.5.12"]
Optionally, the parts can be required separately.
(require '[reitit.core :as r])
(def router
(r/router
[["/api/ping" ::ping]
["/api/orders/:id" ::order-by-id]]))
Routing:
(r/match-by-path router "/api/ipa")
; nil
(r/match-by-path router "/api/ping")
; #Match{:template "/api/ping"
; :data {:name ::ping}
; :result nil
; :path-params {}
; :path "/api/ping"}
(r/match-by-path router "/api/orders/1")
; #Match{:template "/api/orders/:id"
; :data {:name ::order-by-id}
; :result nil
; :path-params {:id "1"}
; :path "/api/orders/1"}
Reverse-routing:
(r/match-by-name router ::ipa)
; nil
(r/match-by-name router ::ping)
; #Match{:template "/api/ping"
; :data {:name ::ping}
; :result nil
; :path-params {}
; :path "/api/ping"}
(r/match-by-name router ::order-by-id)
; #PartialMatch{:template "/api/orders/:id"
; :data {:name :user/order-by-id}
; :result nil
; :path-params nil
; :required #{:id}}
(r/partial-match? (r/match-by-name router ::order-by-id))
; true
(r/match-by-name router ::order-by-id {:id 2})
; #Match{:template "/api/orders/:id",
; :data {:name ::order-by-id},
; :result nil,
; :path-params {:id 2},
; :path "/api/orders/2"}
Ring-router adds support for :handler
functions, :middleware
and routing based on :request-method
. It also supports pluggable parameter coercion (clojure.spec
), data-driven middleware, route and middleware compilation, dynamic extensions and more.
(require '[reitit.ring :as ring])
(defn handler [_]
{:status 200, :body "ok"})
(defn wrap [handler id]
(fn [request]
(update (handler request) :wrap (fnil conj '()) id)))
(def app
(ring/ring-handler
(ring/router
["/api" {:middleware [[wrap :api]]}
["/ping" {:get handler
:name ::ping}]
["/admin" {:middleware [[wrap :admin]]}
["/users" {:get handler
:post handler}]]])))
Routing:
(app {:request-method :get, :uri "/api/admin/users"})
; {:status 200, :body "ok", :wrap (:api :admin}
(app {:request-method :put, :uri "/api/admin/users"})
; nil
Reverse-routing:
(require '[reitit.core :as r])
(-> app (ring/get-router) (r/match-by-name ::ping))
; #Match{:template "/api/ping"
; :data {:middleware [[#object[user$wrap] :api]]
; :get {:handler #object[user$handler]}
; :name ::ping}
; :result #Methods{...}
; :path-params nil
; :path "/api/ping"}