A fast data-driven routing library for Clojure/Script
Find a file
2025-10-10 12:50:24 +03:00
.clj-kondo Setup clj-kondo files for each module 2022-01-24 12:39:42 +02:00
.github/workflows Drop Java 8 tests and support 2025-03-28 15:40:26 +02:00
.lsp format-ns 2022-02-14 16:59:20 +02:00
dev-resources Add mime-types option to static handler 2025-04-07 20:35:58 -04:00
doc No need to use specific Java version for releases 2025-05-27 14:35:50 +03:00
examples Release 0.9.1 2025-05-27 14:04:31 +03:00
modules doc: multipart-middleware should be after coerce-request-middleware 2025-10-10 12:50:24 +03:00
perf-test/clj/reitit Faster path conflict resolution, O(n2) -> O(n) 2020-04-27 08:38:27 +03:00
scripts Cleanup 2025-01-22 13:36:59 +02:00
test feat: allow multimethods as :handlers in validation 2025-10-07 15:50:51 +03:00
.gitignore Add mime-types option to static handler 2025-04-07 20:35:58 -04:00
bb.edn Add bb tasks for Cljs tests 2025-01-22 13:57:10 +02:00
book.json initial rework 2018-09-02 19:23:18 +03:00
CHANGELOG.md doc: update CHANGELOG.md 2025-10-09 15:30:55 +03:00
CONTRIBUTING.md Fix typos 2019-05-22 19:17:10 +02:00
karma.conf.js Cleanup 2025-01-22 13:36:59 +02:00
LICENSE Initial commit 2017-08-07 14:15:45 +03:00
lint.sh Add clj-kondo and fix most linting warnings 2020-03-05 13:32:48 +02:00
package-lock.json test: bump openapi-schema-validator 2025-05-12 14:28:19 +03:00
package.json test: bump openapi-schema-validator 2025-05-12 14:28:19 +03:00
project.clj Release 0.9.1 2025-05-27 14:04:31 +03:00
README.md Release 0.9.1 2025-05-27 14:04:31 +03:00
shadow-cljs.edn Cleanup 2025-01-22 13:36:59 +02:00

reitit

Build Status cljdoc badge Clojars Project Slack

A fast data-driven router for Clojure(Script).

Presentations:

Status: stable

Hi! We are Metosin, a consulting company. These libraries have evolved out of the work we do for our clients. We maintain & develop this project, for you, for free. Issues and pull requests welcome! However, if you want more help using the libraries, or want us to build something as cool for you, consider our commercial support.

Full Documentation

There is #reitit in Clojurians Slack for discussion & help.

Main Modules

  • metosin/reitit - all bundled
  • metosin/reitit-core - the routing core
  • metosin/reitit-ring - a ring router
  • metosin/reitit-middleware - common middleware
  • metosin/reitit-spec clojure.spec coercion
  • metosin/reitit-malli malli coercion
  • metosin/reitit-schema Schema coercion
  • fi.metosin/reitit-openapi OpenAPI apidocs *
  • metosin/reitit-swagger Swagger2 apidocs
  • metosin/reitit-swagger-ui Integrated Swagger UI
  • metosin/reitit-frontend Tools for frontend routing
  • metosin/reitit-http http-routing with Interceptors
  • metosin/reitit-interceptors - common interceptors
  • metosin/reitit-sieppari support for Sieppari
  • metosin/reitit-dev - development utilities

... * This is not a typo; the new reitit-openapi was released under the new, verified fi.metosin group. Existing modules will continue to be released under metosin for compatibility purposes.

Extra modules

Latest version

All main modules bundled:

[metosin/reitit "0.9.1"]

Optionally, the parts can be required separately.

Reitit requires Clojure 1.11 and Java 11.

Reitit is tested with the LTS releases Java 11, 17 and 21.

Quick start

(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"}

Ring example

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.exception :as exception])
(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 ; decoding query & form params
                           muuntaja/format-middleware       ; content negotiation
                           exception/exception-middleware   ; converting exceptions to HTTP responses
                           rrc/coerce-request-middleware
                           rrc/coerce-response-middleware]}})))

Valid request:

(-> (app {:request-method :get
          :uri "/api/math"
          :query-params {:x "1", :y "2"}})
    (update :body slurp))
; {:status 200
;  :body "{\"total\":3}"
;  :headers {"Content-Type" "application/json; charset=utf-8"}}

Invalid request:

(-> (app {:request-method :get
          :uri "/api/math"
          :query-params {:x "1", :y "a"}})
    (update :body jsonista.core/read-value))
; {:status 400
;  :headers {"Content-Type" "application/json; charset=utf-8"}
;  :body {"spec" "(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:spec$8974/x :spec$8974/y]), :type :map, :leaf? false})"
;         "value" {"x" "1"
;                  "y" "a"}
;         "problems" [{"via" ["spec$8974/y"]
;                      "path" ["y"]
;                      "pred" "clojure.core/int?"
;                      "in" ["y"]
;                      "val" "a"}]
;         "type" "reitit.coercion/request-coercion"
;         "coercion" "spec"
;         "in" ["request" "query-params"]}}

More examples

All examples are in https://github.com/metosin/reitit/tree/master/examples

External resources

More info

Check out the full documentation!

Join #reitit channel in Clojurians slack.

Roadmap is mostly written in issues.

Special thanks

License

Copyright © 2017-2023 Metosin Oy

Distributed under the Eclipse Public License, the same as Clojure.