diff --git a/modules/reitit-middleware/src/reitit/ring/middleware/exception.clj b/modules/reitit-middleware/src/reitit/ring/middleware/exception.clj index 895f21ea..f36fc5e9 100644 --- a/modules/reitit-middleware/src/reitit/ring/middleware/exception.clj +++ b/modules/reitit-middleware/src/reitit/ring/middleware/exception.clj @@ -2,26 +2,6 @@ (:require [reitit.coercion :as coercion] [reitit.ring :as ring])) -(defn- super-classes [^Class k] - (loop [sk (.getSuperclass k), ks []] - (if-not (= sk Object) - (recur (.getSuperclass sk) (conj ks sk)) - ks))) - -(defn- call-error-handler [default-handler handlers error request] - (let [{:keys [type] :as data} (ex-data error) - ex-class (class error) - error-handler (or (get handlers type) - (get handlers ex-class) - (some - (partial get handlers) - (descendants type)) - (some - (partial get handlers) - (super-classes ex-class)) - default-handler)] - (error-handler error data request))) - (defn default-handler [^Exception e _ _] {:status 500 :body {:type "exception" @@ -42,6 +22,46 @@ :headers {"Content-Type" "text/plain"} :body (str "Malformed " (pr-str format) " request.")}) +(defn- super-classes [^Class k] + (loop [sk (.getSuperclass k), ks []] + (if-not (= sk Object) + (recur (.getSuperclass sk) (conj ks sk)) + ks))) + +(defn- call-error-handler [handlers error request] + (let [{:keys [type] :as data} (ex-data error) + ex-class (class error) + error-handler (or (get handlers type) + (get handlers ex-class) + (some + (partial get handlers) + (descendants type)) + (some + (partial get handlers) + (super-classes ex-class)) + (get handlers ::default default-handler))] + (error-handler error data request))) + +(defn- on-exception [e handlers request respond raise] + (try + (respond (call-error-handler handlers e request)) + (catch Exception e + (raise e)))) + +(defn- wrap [options] + (fn [handler] + (fn + ([request] + (try + (handler request) + (catch Throwable e + (on-exception options e request identity #(throw %))))) + ([request respond raise] + (try + (handler request respond (fn [e] (on-exception options e request respond raise))) + (catch Throwable e + (on-exception options e request respond raise))))))) + ;; ;; public api ;; @@ -53,32 +73,19 @@ ::coercion/request-coercion (coercion-handler 400) ::coercion/response-coercion (coercion-handler 500)}) -(defn create-exceptions-middleware +(def exception-middleware "Catches all exceptions and looks up a exception handler: 1) `:type` of ex-data 2) Class of Exception 3) descadents `:type` of ex-data 4) Super Classes of Exception 5) The ::default handler" + {:name ::exception + :wrap (wrap default-options)}) + +(defn create-exception-middleware ([] - (create-exceptions-middleware default-options)) + (create-exception-middleware default-options)) ([options] - (let [default-handler (get options ::default default-handler) - on-exception (fn [e request respond raise] - (try - (respond (call-error-handler default-handler options e request)) - (catch Exception e - (raise e))))] - {:name ::exception - :wrap (fn [handler] - (fn - ([request] - (try - (handler request) - (catch Throwable e - (on-exception e request identity #(throw %))))) - ([request respond raise] - (try - (handler request respond (fn [e] (on-exception e request respond raise))) - (catch Throwable e - (on-exception e request respond raise))))))}))) + {:name ::exception + :wrap (wrap options)})) diff --git a/test/clj/reitit/ring/middleware/exception_test.clj b/test/clj/reitit/ring/middleware/exception_test.clj index fe7d6733..d4991a4e 100644 --- a/test/clj/reitit/ring/middleware/exception_test.clj +++ b/test/clj/reitit/ring/middleware/exception_test.clj @@ -22,7 +22,7 @@ :parameters {:query {:x int?, :y int?}} :responses {200 {:body {:total pos-int?}}} :handler f}]] - {:data {:middleware [(exception/create-exceptions-middleware + {:data {:middleware [(exception/create-exception-middleware (merge exception/default-options {::kikka (constantly {:status 200, :body "kikka"})