mirror of
https://github.com/metosin/reitit.git
synced 2026-01-23 22:59:02 +00:00
Exception middleware revisited
This commit is contained in:
parent
62cdfa2c52
commit
2ab54a1b99
2 changed files with 90 additions and 39 deletions
|
|
@ -1,6 +1,14 @@
|
||||||
(ns reitit.ring.middleware.exception
|
(ns reitit.ring.middleware.exception
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [reitit.coercion :as coercion]
|
||||||
[reitit.ring :as ring]))
|
[reitit.ring :as ring]
|
||||||
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(s/def ::handlers (s/map-of any? fn?))
|
||||||
|
(s/def ::spec (s/keys :opt-un [::handlers]))
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; helpers
|
||||||
|
;;
|
||||||
|
|
||||||
(defn- super-classes [^Class k]
|
(defn- super-classes [^Class k]
|
||||||
(loop [sk (.getSuperclass k), ks []]
|
(loop [sk (.getSuperclass k), ks []]
|
||||||
|
|
@ -28,6 +36,20 @@
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(raise e))))
|
(raise e))))
|
||||||
|
|
||||||
|
(defn- wrap [{:keys [handlers]}]
|
||||||
|
(fn [handler]
|
||||||
|
(fn
|
||||||
|
([request]
|
||||||
|
(try
|
||||||
|
(handler request)
|
||||||
|
(catch Throwable e
|
||||||
|
(on-exception handlers e request identity #(throw %)))))
|
||||||
|
([request respond raise]
|
||||||
|
(try
|
||||||
|
(handler request respond (fn [e] (on-exception handlers e request respond raise)))
|
||||||
|
(catch Throwable e
|
||||||
|
(on-exception handlers e request respond raise)))))))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; handlers
|
;; handlers
|
||||||
;;
|
;;
|
||||||
|
|
@ -60,51 +82,80 @@
|
||||||
;; public api
|
;; public api
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(def default-handlers
|
(def default-options
|
||||||
{::default default-handler
|
{:handlers {::default default-handler
|
||||||
::ring/response http-response-handler
|
::ring/response http-response-handler
|
||||||
:muuntaja/decode request-parsing-handler
|
:muuntaja/decode request-parsing-handler
|
||||||
::coercion/request-coercion (create-coercion-handler 400)
|
::coercion/request-coercion (create-coercion-handler 400)
|
||||||
::coercion/response-coercion (create-coercion-handler 500)})
|
::coercion/response-coercion (create-coercion-handler 500)}})
|
||||||
|
|
||||||
(defn wrap-exception [handlers]
|
(defn wrap-exception
|
||||||
(fn [handler]
|
"Ring middleware that catches all exceptions and looks up a
|
||||||
(fn
|
exceptions handler of type `exception request => response` to
|
||||||
([request]
|
handle the exception.
|
||||||
(try
|
|
||||||
(handler request)
|
The following options are supported:
|
||||||
(catch Throwable e
|
|
||||||
(on-exception handlers e request identity #(throw %)))))
|
| key | description
|
||||||
([request respond raise]
|
|--------------|-------------
|
||||||
(try
|
| `:handlers` | A map of exception identifier => exception-handler
|
||||||
(handler request respond (fn [e] (on-exception handlers e request respond raise)))
|
|
||||||
(catch Throwable e
|
The handler is selected from the handlers by exception idenfiter
|
||||||
(on-exception handlers e request respond raise)))))))
|
in the following lookup order:
|
||||||
|
|
||||||
|
1) `:type` of exception ex-data
|
||||||
|
2) Class of exception
|
||||||
|
3) descadents `:type` of exception ex-data
|
||||||
|
4) Super Classes of exception
|
||||||
|
5) The ::default handler"
|
||||||
|
[handler options]
|
||||||
|
(-> options wrap handler))
|
||||||
|
|
||||||
(def exception-middleware
|
(def exception-middleware
|
||||||
"Middleware that catches all exceptions and looks up a exception handler
|
"Reitit middleware that catches all exceptions and looks up a
|
||||||
from a [[default-handlers]] map in the lookup order:
|
exceptions handler of type `exception request => response` to
|
||||||
|
handle the exception.
|
||||||
|
|
||||||
1) `:type` of ex-data
|
The following options are supported:
|
||||||
2) Class of Exception
|
|
||||||
3) descadents `:type` of ex-data
|
| key | description
|
||||||
4) Super Classes of Exception
|
|--------------|-------------
|
||||||
|
| `:handlers` | A map of exception identifier => exception-handler
|
||||||
|
|
||||||
|
The handler is selected from the handlers by exception idenfiter
|
||||||
|
in the following lookup order:
|
||||||
|
|
||||||
|
1) `:type` of exception ex-data
|
||||||
|
2) Class of exception
|
||||||
|
3) descadents `:type` of exception ex-data
|
||||||
|
4) Super Classes of exception
|
||||||
5) The ::default handler"
|
5) The ::default handler"
|
||||||
{:name ::exception
|
{:name ::exception
|
||||||
:wrap (wrap-exception default-handlers)})
|
:spec ::spec
|
||||||
|
:wrap (wrap default-options)})
|
||||||
|
|
||||||
(defn create-exception-middleware
|
(defn create-exception-middleware
|
||||||
"Creates a middleware that catches all exceptions and looks up a exception handler
|
"Creates a reitit middleware that catches all exceptions and looks up a
|
||||||
from a given map of `handlers` with keyword or Exception class as keys and a 2-arity
|
exceptions handler of type `exception request => response` to
|
||||||
Exception handler function as values.
|
handle the exception.
|
||||||
|
|
||||||
1) `:type` of ex-data
|
The following options are supported:
|
||||||
2) Class of Exception
|
|
||||||
3) descadents `:type` of ex-data
|
| key | description
|
||||||
4) Super Classes of Exception
|
|--------------|-------------
|
||||||
|
| `:handlers` | A map of exception identifier => exception-handler
|
||||||
|
|
||||||
|
The handler is selected from the handlers by exception idenfiter
|
||||||
|
in the following lookup order:
|
||||||
|
|
||||||
|
1) `:type` of exception ex-data
|
||||||
|
2) Class of exception
|
||||||
|
3) descadents `:type` of exception ex-data
|
||||||
|
4) Super Classes of exception
|
||||||
5) The ::default handler"
|
5) The ::default handler"
|
||||||
([]
|
([]
|
||||||
(create-exception-middleware default-handlers))
|
(create-exception-middleware default-options))
|
||||||
([handlers]
|
([options]
|
||||||
{:name ::exception
|
{:name ::exception
|
||||||
:wrap (wrap-exception handlers)}))
|
:spec ::spec
|
||||||
|
:wrap (wrap options)}))
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
:responses {200 {:body {:total pos-int?}}}
|
:responses {200 {:body {:total pos-int?}}}
|
||||||
:handler f}]]
|
:handler f}]]
|
||||||
{:data {:middleware [(exception/create-exception-middleware
|
{:data {:middleware [(exception/create-exception-middleware
|
||||||
(merge
|
(update
|
||||||
exception/default-handlers
|
exception/default-options :handlers merge
|
||||||
{::kikka (constantly {:status 200, :body "kikka"})
|
{::kikka (constantly {:status 200, :body "kikka"})
|
||||||
SQLException (constantly {:status 200, :body "sql"})}))]}})))]
|
SQLException (constantly {:status 200, :body "sql"})}))]}})))]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue