Ring is a Clojure web applications library inspired by Python's WSGI and Ruby's Rack. By abstracting the details of HTTP into a simple, unified API, Ring allows web applications to be constructed of modular components that can be shared among a variety of applications, web servers, and web frameworks.
Read more about the Ring Concepts.
[fi.metosin/reitit-ring "0.7.0-alpha5"]
reitit.ring/routerreitit.ring/router is a higher order router, which adds support for :request-method based routing, handlers and middleware.
It accepts the following options:
| key | description | 
|---|---|
| :reitit.middleware/transform | Function of [Middleware] => [Middleware]to transform the expanded Middleware (default: identity). | 
| :reitit.middleware/registry | Map of keyword => IntoMiddlewareto replace keyword references into Middleware | 
| :reitit.ring/default-options-endpoint | Default endpoint for :optionsmethod (default: default-options-endpoint) | 
Example router:
(require '[reitit.ring :as ring])
(defn handler [_]
  {:status 200, :body "ok"})
(def router
  (ring/router
    ["/ping" {:get handler}]))
Match contains :result compiled by reitit.ring/router:
(require '[reitit.core :as r])
(r/match-by-path router "/ping")
;#Match{:template "/ping"
;       :data {:get {:handler #object[...]}}
;       :result #Methods{:get #Endpoint{...}
;                        :options #Endpoint{...}}
;       :path-params {}
;       :path "/ping"}
reitit.ring/ring-handlerGiven a router from reitit.ring/router, optional default-handler & options, ring-handler function will return a valid ring handler supporting both synchronous and asynchronous request handling. The following options are available:
| key | description | 
|---|---|
| :middleware | Optional sequence of middlewares that wrap the ring-handler | 
| :inject-match? | Boolean to inject matchinto request under:reitit.core/matchkey (default true) | 
| :inject-router? | Boolean to inject routerinto request under:reitit.core/routerkey (default true) | 
Simple Ring app:
(def app (ring/ring-handler router))
Applying the handler:
(app {:request-method :get, :uri "/favicon.ico"})
; nil
(app {:request-method :get, :uri "/ping"})
; {:status 200, :body "ok"}
The router can be accessed via get-router:
(-> app (ring/get-router) (r/compiled-routes))
;[["/ping"
;  {:handler #object[...]}
;  #Methods{:get #Endpoint{:data {:handler #object[...]}
;                          :handler #object[...]
;                          :middleware []}
;           :options #Endpoint{:data {:handler #object[...]}
;                              :handler #object[...]
;                              :middleware []}}]]
Handlers can be placed either to the top-level (all methods) or under a specific method (:get, :head, :patch, :delete, :options, :post, :put or :trace). Top-level handler is used if request-method based handler is not found.
By default, the :options route is generated for all paths - to enable thing like CORS.
(def app
  (ring/ring-handler
    (ring/router
      [["/all" handler]
       ["/ping" {:name ::ping
                 :get handler
                 :post handler}]])))
Top-level handler catches all methods:
(app {:request-method :delete, :uri "/all"})
; {:status 200, :body "ok"}
Method-level handler catches only the method:
(app {:request-method :get, :uri "/ping"})
; {:status 200, :body "ok"}
(app {:request-method :put, :uri "/ping"})
; nil
By default, :options is also supported (see router options to change this):
(app {:request-method :options, :uri "/ping"})
; {:status 200, :body ""}
Name-based reverse routing:
(-> app
    (ring/get-router)
    (r/match-by-name ::ping)
    (r/match->path))
; "/ping"
Middleware can be mounted using a :middleware key - either to top-level or under request method submap. Its value should be a vector of reitit.middleware/IntoMiddleware values. These include:
handler -> request -> response[handler args*] -> request -> response and it's argumentsA middleware and a handler:
(defn wrap [handler id]
  (fn [request]
    (handler (update request ::acc (fnil conj []) id))))
(defn handler [{::keys [acc]}]
  {:status 200, :body (conj acc :handler)})
App with nested middleware:
(def app
  (ring/ring-handler
    (ring/router
      ;; a middleware function
      ["/api" {:middleware [#(wrap % :api)]}
       ["/ping" handler]
       ;; a middleware vector at top level
       ["/admin" {:middleware [[wrap :admin]]}
        ["/db" {:middleware [[wrap :db]]
                ;; a middleware vector at under a method
                :delete {:middleware [[wrap :delete]]
                         :handler handler}}]]])))
Middleware is applied correctly:
(app {:request-method :delete, :uri "/api/ping"})
; {:status 200, :body [:api :handler]}
(app {:request-method :delete, :uri "/api/admin/db"})
; {:status 200, :body [:api :admin :db :delete :handler]}
Top-level middleware, applied before any routing is done:
(def app
  (ring/ring-handler
    (ring/router
      ["/api" {:middleware [[mw :api]]}
       ["/get" {:get handler}]])
    nil
    {:middleware [[mw :top]]}))
(app {:request-method :get, :uri "/api/get"})
; {:status 200, :body [:top :api :ok]}
Can you improve this documentation? These fine people already did:
Tommi Reiman, Juho Teperi, Miikka Koskinen, Joel Kaasinen, bplubell, Phil Hofmann & Alexander KielEdit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs | 
| ← | Move to previous article | 
| → | Move to next article | 
| Ctrl+/ | Jump to the search field |