Lifts ring-defaults middleware into data-driven middleware, providing sensible defaults per route.
Reitit provides advanced middleware capabilities and comes with a small number of "standard" middleware. For many common tasks such as session management, additional middleware is required.
Many people use wrap-defaults
from ring-defaults as a sensible default
chain. However, some middleware included in site-defaults
will conflict with
an idiomatic Reitit setup:
create-resource-handler
and create-file-handler
The result is a sub-optimal performance and developer's confusion when requests are not handled as expected.
Furthermore, it is not obvious at which place in Reitit's configuration
wrap-defaults
should go.
deps.edn:
com.fbeyer/reitit-ring-defaults {:mvn/version "0.1.0"}
Leiningen/Boot:
[com.fbeyer/reitit-ring-defaults "0.1.0"]
The ring-defaults-middleware
is designed as a replacement for wrap-defaults
.
In order to have any effect, you will need to add a :defaults
key to your
route data. A good starting point is one of the curated configurations
provided by ring-defaults, such as api-defaults
:
(require '[reitit.ring :as ring]
'[reitit.ring.middleware.defaults :refer [ring-defaults-middleware]]
'[ring.middleware.defaults :refer [api-defaults]])
;; ...
(def app
(ring/ring-handler
(ring/router
["/api"
{:middleware [ring-defaults-middleware]
:defaults apu-defaults}
["/ping" handler]
["/pong" handler]]
routes)))
You can treat the :defaults
data like any other route data: You can specify
it globally or per-route, and route configurations will be merged with parent
configurations.
Any middleware not configured per route will not mount, and have zero runtime impact.
Reitit provides excellent support for content negotiation and coercion.
Since it is very common to use these, and opting out has no runtime penalty,
there is a defaults-middleware
that includes additional Reitit middleware
as a sensible default.
Like wrap-defaults
, reitit-defaults-middleware includes Ring's wrap-session
,
and using its default configuration in Reitit route data will have surprising
effects, as Reitit will mount one instance per route.
The recommended solution with reitit-defaults-middleware is to explicitly configure a session store. Since the default in-memory store will not be suitable for non-trivial production deployments, you will want to do that anyway.
(require '[ring.middleware.session.memory :as memory])
;; single instance
(def session-store (memory/memory-store))
;; inside, with shared store
(def app
(ring/ring-handler
(ring/router
["/api"
{:middleware [ring-defaults-middleware]
:defaults (-> site-defaults
(assoc-in [:session :store] session-store))}
["/ping" handler]
["/pong" handler]])))
Copyright 2022 Ferdinand Beyer.
Distributed under the MIT License.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close