See the readme of Stylitics' fork of ring-clojure for instructions
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 (malli, schema & clojure.spec)
- Helpers for ring, http, pedestal & frontend
- Friendly Error Messages
- Extendable
- Modular
- Fast
Presentations:
- Reitit, The Ancient Art of Data-Driven, Clojure/North 2019, video
- Faster and Friendlier Routing with Reitit 0.3.0
- Welcome Reitit 0.2.0!
- Data-Driven Ring with Reitit
- Reitit, Data-Driven Routing with Clojure(Script)
Status: stable
There is #reitit in Clojurians Slack for discussion & help.
- 
metosin/reitit- all bundled
- 
metosin/reitit-core- the routing core
- 
metosin/reitit-ring- a ring router
- 
metosin/reitit-middleware- common middleware
- 
metosin/reitit-specclojure.spec coercion
- 
metosin/reitit-mallimalli coercion
- 
metosin/reitit-schemaSchema coercion
- 
fi.metosin/reitit-openapiOpenAPI apidocs *
- 
metosin/reitit-swaggerSwagger2 apidocs
- 
metosin/reitit-swagger-uiIntegrated Swagger UI
- 
metosin/reitit-frontendTools for frontend routing
- 
metosin/reitit-httphttp-routing with Interceptors
- 
metosin/reitit-interceptors- common interceptors
- 
metosin/reitit-siepparisupport for Sieppari
- 
metosin/reitit-dev- development utilities
- 
- This is not a typo; the new reitit-openapiwas released under the new, verifiedfi.metosingroup. Existing modules will continue to be released undermetosinfor compatibility purposes.
 
- This is not a typo; the new 
- reitit-pedestalsupport for Pedestal
All main modules bundled:
[metosin/reitit "0.7.1"]Optionally, the parts can be required separately.
Malli requires Clojure 1.11.
Malli is tested with the LTS releases Java 8, 11, 17 and 21.
(require '[reitit.core :as r])
(def router
  (r/router
    [["/api/ping" ::ping]
     ["/api/orders/:id" ::order]]))
(r/match-by-path router "/api/ping")
; #Match{:template "/api/ping"
;        :data {:name ::ping}
;        :result nil
;        :path-params {}
;        :path "/api/ping"}
(r/match-by-name router ::order {:id 2})
; #Match{:template "/api/orders/:id",
;        :data {:name ::order},
;        :result nil,
;        :path-params {:id 2},
;        :path "/api/orders/2"}A Ring routing app with input & output coercion using data-specs.
(require '[muuntaja.core :as m])
(require '[reitit.ring :as ring])
(require '[reitit.coercion.spec])
(require '[reitit.ring.coercion :as rrc])
(require '[reitit.ring.middleware.muuntaja :as muuntaja])
(require '[reitit.ring.middleware.parameters :as parameters])
(def app
  (ring/ring-handler
    (ring/router
      ["/api"
       ["/math" {:get {:parameters {:query {:x int?, :y int?}}
                       :responses  {200 {:body {:total int?}}}
                       :handler    (fn [{{{:keys [x y]} :query} :parameters}]
                                     {:status 200
                                      :body   {:total (+ x y)}})}}]]
      ;; router data affecting all routes
      {:data {:coercion   reitit.coercion.spec/coercion
              :muuntaja   m/instance
              :middleware [parameters/parameters-middleware
                           rrc/coerce-request-middleware
                           muuntaja/format-response-middleware
                           rrc/coerce-response-middleware]}})))Valid request:
(app {:request-method :get
      :uri "/api/math"
      :query-params {:x "1", :y "2"}})
; {:status 200
;  :body {:total 3}}Invalid request:
(app {:request-method :get
      :uri "/api/math"
      :query-params {:x "1", :y "a"}})
;{:status 400,
; :body {:type :reitit.coercion/request-coercion,
;        :coercion :spec,
;        :spec "(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:$spec20745/x :$spec20745/y]), :type :map, :keys #{:y :x}, :keys/req #{:y :x}})",
;        :problems [{:path [:y],
;                    :pred "clojure.core/int?",
;                    :val "a",
;                    :via [:$spec20745/y],
;                    :in [:y]}],
;        :value {:x "1", :y "a"},
;        :in [:request :query-params]}}- reitit-ringwith coercion, swagger and default middleware
- reitit-frontend, the easy way
- reitit-frontendwith Keechma-style controllers
- reitit-httpwith Pedestal
- reitit-httpwith Sieppari
All examples are in https://github.com/metosin/reitit/tree/master/examples
- Simple web application using Ring/Reitit and Integrant: https://github.com/PrestanceDesign/usermanager-reitit-integrant-example
- A simple Clojure backend using Reitit to serve up a RESTful API: startrek. Technologies include:
- https://www.learnreitit.com/
- Lipas, liikuntapalvelut: https://github.com/lipas-liikuntapaikat/lipas
- Implementation of the Todo-Backend API spec, using Clojure, Ring/Reitit and next-jdbc: https://github.com/PrestanceDesign/todo-backend-clojure-reitit
- Ping CRM, a single page app written in Clojure Ring, Reitit, Integrant and next.jdbc: https://github.com/prestancedesign/clojure-inertia-pingcrm-demo
Check out the full documentation!
Join #reitit channel in Clojurians slack.
Roadmap is mostly written in issues.
- Existing Clojure(Script) routing libs, especially to Ataraxy, Bide, Bidi, calfpath, Compojure, Keechma and Pedestal.
- Compojure-api, Kekkonen, Ring-swagger and Yada and for ideas, coercion & stuff.
- Schema and clojure.spec for the validation part.
- httprouter for ideas and a good library to benchmark against
Copyright © 2017-2023 Metosin Oy
Distributed under the Eclipse Public License, the same as Clojure.