Merge pull request #772 from metosin/fix/768-ancestors

fix create-exception-middleware for hierarchical keywords
This commit is contained in:
Joel Kaasinen 2026-01-09 09:35:14 +02:00 committed by GitHub
commit 1d4473e1f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 6 deletions

View file

@ -19,17 +19,17 @@
(recur (.getSuperclass sk) (conj ks sk))
ks)))
(defn- descendants-safe [type]
(when-not (class? type) (descendants type)))
(defn- find-closest-ancestor [val m]
(or (get m val)
(some #(find-closest-ancestor % m) (parents val))))
(defn- call-error-handler [handlers error request]
(let [type (:type (ex-data error))
ex-class (class error)
error-handler (or (get handlers type)
(get handlers ex-class)
(some
(partial get handlers)
(descendants-safe type))
(when-not (class? type)
(find-closest-ancestor type handlers))
(some
(partial get handlers)
(super-classes ex-class))
@ -143,6 +143,9 @@
4) Super Classes of exception
5) The ::default handler
Note! If the closest ancestor for `:type` is not unique, an
arbitrary one is picked.
Example:
(require '[reitit.ring.middleware.exception :as exception])

View file

@ -11,7 +11,7 @@
(:import (clojure.lang ExceptionInfo)
(java.sql SQLException SQLWarning)))
(derive ::kikka ::kukka)
(derive ::kukka ::kikka)
(deftest exception-test
(letfn [(create
@ -147,6 +147,55 @@
(is (= status 500))
(is (= body "too many tries")))))))
(derive ::table ::object)
(derive ::living ::object)
(derive ::plant ::living)
(derive ::animal ::living)
(derive ::dog ::animal)
(derive ::cat ::animal)
(derive ::garfield ::cat)
(deftest exception-hierarchy-test
(letfn [(create [f]
(ring/ring-handler
(ring/router
[["/defaults"
{:handler f}]]
{:data {:middleware [(exception/create-exception-middleware
(merge
exception/default-handlers
{::object (constantly (http-response/bad-request "object"))
::living (constantly (http-response/bad-request "living"))
::animal (constantly (http-response/bad-request "animal"))
::cat (constantly (http-response/bad-request "cat"))}))]}})))
(call [ex-typ]
(let [app (create (fn [_] (throw (ex-info "fail" {:type ex-typ}))))]
(app {:request-method :get, :uri "/defaults"})))]
(let [{:keys [status body]} (call ::object)]
(is (= status 400))
(is (= body "object")))
(let [{:keys [status body]} (call ::table)]
(is (= status 400))
(is (= body "object")))
(let [{:keys [status body]} (call ::living)]
(is (= status 400))
(is (= body "living")))
(let [{:keys [status body]} (call ::plant)]
(is (= status 400))
(is (= body "living")))
(let [{:keys [status body]} (call ::animal)]
(is (= status 400))
(is (= body "animal")))
(let [{:keys [status body]} (call ::dog)]
(is (= status 400))
(is (= body "animal")))
(let [{:keys [status body]} (call ::cat)]
(is (= status 400))
(is (= body "cat")))
(let [{:keys [status body]} (call ::garfield)]
(is (= status 400))
(is (= body "cat")))))
(deftest spec-coercion-exception-test
(let [app (ring/ring-handler
(ring/router