Top Related Projects
Quick Overview
Reitit is a fast and flexible HTTP router for Clojure and ClojureScript. It provides a modular and extensible routing system that supports various features such as path parameters, route hierarchy, and middleware.
Pros
- Performance: Reitit is designed to be fast and efficient, with a focus on performance.
- Flexibility: The routing system is highly customizable and can be extended with various middleware and plugins.
- Modular Design: Reitit is designed with a modular approach, allowing developers to use only the features they need.
- ClojureScript Support: Reitit supports both Clojure and ClojureScript, making it a versatile choice for web development.
Cons
- Learning Curve: Reitit's flexibility and feature-rich nature may have a steeper learning curve for developers new to Clojure or ClojureScript.
- Ecosystem: Compared to some other web frameworks, the Reitit ecosystem may be smaller, with fewer third-party libraries and resources available.
- Documentation: While the documentation is generally good, some developers may find it could be more comprehensive or easier to navigate.
- Adoption: Reitit is not as widely adopted as some other Clojure/ClojureScript web frameworks, which may make it harder to find community support or resources.
Code Examples
Here are a few examples of how to use Reitit:
- Basic Routing:
(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
["/api"
["/users" ::users]
["/posts" ::posts]])))
This example sets up a basic routing structure with two routes: /api/users
and /api/posts
.
- Path Parameters:
(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
["/api/users/:id" ::user-details])))
This example demonstrates how to define a route with a path parameter, which can be accessed in the handler function.
- Middleware:
(require '[reitit.ring :as ring]
'[reitit.ring.middleware.muuntaja :as muuntaja]
'[reitit.ring.middleware.exception :as exception]
'[reitit.ring.middleware.parameters :as parameters])
(def app
(ring/ring-handler
(ring/router
["/api"
{:middleware [muuntaja/format-negotiate-middleware
muuntaja/format-response-middleware
parameters/parameters-middleware
exception/exception-middleware]}
["/users" ::users]
["/posts" ::posts]])))
This example shows how to apply middleware to a set of routes, in this case, handling request/response formatting, parameter parsing, and exception handling.
Getting Started
To get started with Reitit, you can follow these steps:
- Add the Reitit dependency to your project:
[metosin/reitit "0.5.15"]
- Require the necessary Reitit namespaces:
(require '[reitit.ring :as ring]
'[reitit.coercion.spec]
'[reitit.swagger]
'[reitit.swagger-ui])
- Define your routes and handlers:
(def routes
["/api"
{:middleware [muuntaja/format-negotiate-middleware
muuntaja/format-response-middleware
parameters/parameters-middleware
exception/exception-middleware]}
["/users" ::users]
["/posts" ::posts]])
(def app
(ring/ring-handler
(ring/router routes
{:data {:coercion reitit.coercion.spec/coercion
:muuntaja m/instance
:middleware [swagger/swagger-feature
exception/exception-middleware]}})))
- Start your application
Competitor Comparisons
The Clojure Interactive Development Environment that Rocks for Emacs
Pros of CIDER
- Provides a rich and integrated development environment for Clojure, with features like a REPL, debugger, and code evaluation.
- Offers seamless integration with Emacs, allowing for a streamlined and efficient workflow.
- Supports a wide range of Clojure libraries and frameworks, including Reitit.
Cons of CIDER
- Requires Emacs, which may not be the preferred editor for some developers.
- The learning curve for Emacs can be steep, especially for those unfamiliar with the editor.
- Dependency on Emacs may limit the portability of the development environment.
Code Comparison
Reitit:
(reitit/router
[["/" :home]
["/about" :about]
["/users/:id" :user]])
CIDER:
(defn my-handler [request]
{:status 200
:body "Hello, World!"})
(def routes
[["/" {:get my-handler}]])
A concise routing library for Ring/Clojure
Pros of Compojure
- Compojure is a lightweight and minimalist web framework, making it a good choice for small to medium-sized projects.
- It has a simple and intuitive syntax, which can be easier to learn and use than more complex frameworks.
- Compojure is well-established and has a large community, with a wealth of resources and documentation available.
Cons of Compojure
- Compojure may lack some of the advanced features and functionality found in more feature-rich frameworks like Reitit.
- The routing system in Compojure is less flexible and powerful than the one in Reitit, which offers more advanced routing capabilities.
- Compojure may not be as well-suited for building large-scale, complex web applications as Reitit.
Code Comparison
Compojure:
(defroutes app-routes
(GET "/" [] "Hello, World!")
(GET "/about" [] "About page")
(POST "/submit" request (handle-submit request)))
Reitit:
(def router
(reitit/router
[["/api"
["/hello" {:get (fn [_] {:status 200, :body "Hello, World!"})}]
["/about" {:get (fn [_] {:status 200, :body "About page"})}]
["/submit" {:post (fn [request] (handle-submit request))}]]]))
The Pedestal Server-side Libraries
Pros of Pedestal
- Pedestal provides a comprehensive set of features for building web applications, including support for routing, middleware, and dependency injection.
- Pedestal has a strong focus on modularity and extensibility, making it easy to integrate with other Clojure libraries and frameworks.
- Pedestal's documentation is well-written and provides detailed examples, making it easier for developers to get started with the framework.
Cons of Pedestal
- Pedestal has a steeper learning curve compared to Reitit, as it requires a deeper understanding of Clojure's core concepts and the framework's architecture.
- Pedestal's performance may not be as optimized as Reitit's, especially for simple web applications that don't require the full set of Pedestal's features.
Code Comparison
Reitit:
(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
[["/hello" ::hello]
["/world" ::world]]
{:data {:middleware [wrap-params]}})))
Pedestal:
(require '[io.pedestal.http :as http])
(defn hello [request]
{:status 200 :body "Hello, World!"})
(def routes
#{["/hello" :get `hello :route-name ::hello]
["/world" :get `hello :route-name ::world]})
(def service-map
{::http/routes routes
::http/type :jetty
::http/port 8080})
Clojure HTTP server abstraction
Pros of ring-clojure/ring
- Simplicity: Ring provides a simple and lightweight API for building web applications, making it easy to get started with Clojure web development.
- Flexibility: Ring allows developers to choose their own middleware and libraries, providing a high degree of flexibility in building web applications.
- Extensive Ecosystem: The Clojure community has built a vast ecosystem of libraries and tools that integrate well with Ring, making it a popular choice for Clojure web development.
Cons of ring-clojure/ring
- Lack of Opinionated Routing: Unlike reitit, Ring does not provide an opinionated routing solution, which can lead to more boilerplate code when building complex web applications.
- Limited Functionality: Ring is a low-level library, and developers may need to use additional libraries to implement features like data validation, error handling, and other common web application requirements.
Code Comparison
reitit:
(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
["/api"
["/users" ::users]
["/posts" ::posts]]
{:data {:middleware [wrap-params
wrap-keyword-params
wrap-json-response]}})))
ring:
(require '[ring.adapter.jetty :as jetty]
'[ring.middleware.params :refer [wrap-params]]
'[ring.middleware.keyword-params :refer [wrap-keyword-params]]
'[ring.middleware.json :refer [wrap-json-response]])
(defn app [request]
{:status 200
:headers {"Content-Type" "application/json"}
:body (json/write-str {:message "Hello, World!"})})
(jetty/run-jetty app {:port 3000})
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
reitit

- 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
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 bundledmetosin/reitit-core
- the routing coremetosin/reitit-ring
- a ring routermetosin/reitit-middleware
- common middlewaremetosin/reitit-spec
clojure.spec coercionmetosin/reitit-malli
malli coercionmetosin/reitit-schema
Schema coercionfi.metosin/reitit-openapi
OpenAPI apidocs *metosin/reitit-swagger
Swagger2 apidocsmetosin/reitit-swagger-ui
Integrated Swagger UImetosin/reitit-frontend
Tools for frontend routingmetosin/reitit-http
http-routing with Interceptorsmetosin/reitit-interceptors
- common interceptorsmetosin/reitit-sieppari
support for Siepparimetosin/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
reitit-pedestal
support for Pedestal
Latest version
All main modules bundled:
[metosin/reitit "0.8.0"]
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.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]}}
More examples
reitit-ring
with coercion, swagger and default middlewarereitit-frontend
, the easy wayreitit-frontend
with Keechma-style controllersreitit-http
with Pedestalreitit-http
with Sieppari
All examples are in https://github.com/metosin/reitit/tree/master/examples
External resources
- 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
More info
Check out the full documentation!
Join #reitit channel in Clojurians slack.
Roadmap is mostly written in issues.
Special thanks
- 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
License
Copyright © 2017-2023 Metosin Oy
Distributed under the Eclipse Public License, the same as Clojure.
Top Related Projects
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot