[metosin/reitit-middleware "0.7.0-alpha2"]
Exceptions thrown in router creation can be handled with custom exception handler. By default, exceptions thrown at runtime from a handler or a middleware are not caught by the reitit.ring/ring-handler
. A good practice is to have a top-level exception handler to log and format errors for clients.
(require '[reitit.ring.middleware.exception :as exception])
exception/exception-middleware
A preconfigured middleware using exception/default-handlers
. Catches:
:type
of :reitit.ring/response
, returning :response
key from ex-data
.(require '[reitit.ring :as ring])
(def app
(ring/ring-handler
(ring/router
["/fail" (fn [_] (throw (Exception. "fail")))]
{:data {:middleware [exception/exception-middleware]}})))
(app {:request-method :get, :uri "/fail"})
;{:status 500
; :body {:type "exception"
; :class "java.lang.Exception"}}
exception/create-exception-middleware
Creates the exception-middleware with custom options. Takes a map of identifier => exception request => response
that is used to select the exception handler for the thrown/raised exception identifier. Exception identifier is either a Keyword
or an Exception Class.
The following handlers are available by default:
key | description |
---|---|
:reitit.ring/response | value in ex-data key :response will be returned |
:muuntaja/decode | handle Muuntaja decoding exceptions |
:reitit.coercion/request-coercion | request coercion errors (http 400 response) |
:reitit.coercion/response-coercion | response coercion errors (http 500 response) |
::exception/default | a default exception handler if nothing else matched (default exception/default-handler ). |
::exception/wrap | a 3-arity handler to wrap the actual handler handler exception request => response (no default). |
The handler is selected from the options map by exception identifier in the following lookup order:
:type
of exception ex-data:type
ancestors of exception ex-data::default
handler;; type hierarchy
(derive ::error ::exception)
(derive ::failure ::exception)
(derive ::horror ::exception)
(defn handler [message exception request]
{:status 500
:body {:message message
:exception (.getClass exception)
:data (ex-data exception)
:uri (:uri request)}})
(def exception-middleware
(exception/create-exception-middleware
(merge
exception/default-handlers
{;; ex-data with :type ::error
::error (partial handler "error")
;; ex-data with ::exception or ::failure
::exception (partial handler "exception")
;; SQLException and all it's child classes
java.sql.SQLException (partial handler "sql-exception")
;; override the default handler
::exception/default (partial handler "default")
;; print stack-traces for all exceptions
::exception/wrap (fn [handler e request]
(println "ERROR" (pr-str (:uri request)))
(handler e request))})))
(def app
(ring/ring-handler
(ring/router
["/fail" (fn [_] (throw (ex-info "fail" {:type ::failure})))]
{:data {:middleware [exception-middleware]}})))
(app {:request-method :get, :uri "/fail"})
; ERROR "/fail"
; => {:status 500,
; :body {:message "default"
; :exception clojure.lang.ExceptionInfo
; :data {:type :user/failure}
; :uri "/fail"}}
Can you improve this documentation? These fine people already did:
Tommi Reiman, Miikka Koskinen, Juho Teperi & Phil HofmannEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close