mirror of
https://github.com/metosin/reitit.git
synced 2025-12-20 17:41:11 +00:00
exception middleware tests
This commit is contained in:
parent
b524736776
commit
805cb94d33
3 changed files with 126 additions and 21 deletions
|
|
@ -13,6 +13,9 @@
|
||||||
ex-class (class error)
|
ex-class (class error)
|
||||||
error-handler (or (get handlers type)
|
error-handler (or (get handlers type)
|
||||||
(get handlers ex-class)
|
(get handlers ex-class)
|
||||||
|
(some
|
||||||
|
(partial get handlers)
|
||||||
|
(descendants type))
|
||||||
(some
|
(some
|
||||||
(partial get handlers)
|
(partial get handlers)
|
||||||
(super-classes ex-class))
|
(super-classes ex-class))
|
||||||
|
|
@ -37,13 +40,13 @@
|
||||||
(defn request-parsing-handler [_ {:keys [format]} _]
|
(defn request-parsing-handler [_ {:keys [format]} _]
|
||||||
{:status 400
|
{:status 400
|
||||||
:headers {"Content-Type" "text/plain"}
|
:headers {"Content-Type" "text/plain"}
|
||||||
:body (str "Malformed " format " request.")})
|
:body (str "Malformed " (pr-str format) " request.")})
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; public api
|
;; public api
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(def default-handlers
|
(def default-options
|
||||||
{::default default-handler
|
{::default default-handler
|
||||||
::ring/response http-response-handler
|
::ring/response http-response-handler
|
||||||
:muuntaja/decode request-parsing-handler
|
:muuntaja/decode request-parsing-handler
|
||||||
|
|
@ -54,25 +57,28 @@
|
||||||
"Catches all exceptions and looks up a exception handler:
|
"Catches all exceptions and looks up a exception handler:
|
||||||
1) `:type` of ex-data
|
1) `:type` of ex-data
|
||||||
2) Class of Exception
|
2) Class of Exception
|
||||||
3) Super Classes of Exception
|
3) descadents `:type` of ex-data
|
||||||
4) The ::default handler"
|
4) Super Classes of Exception
|
||||||
|
5) The ::default handler"
|
||||||
([]
|
([]
|
||||||
(create-exceptions-middleware default-handlers))
|
(create-exceptions-middleware default-options))
|
||||||
([{:keys [handlers] :or {handlers default-handlers}}]
|
([options]
|
||||||
(let [default-handler (get handlers ::default default-handler)
|
(let [default-handler (get options ::default default-handler)
|
||||||
on-exception (fn [e request respond raise]
|
on-exception (fn [e request respond raise]
|
||||||
(try
|
(try
|
||||||
(respond (call-error-handler default-handler handlers e request))
|
(respond (call-error-handler default-handler options e request))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(raise e))))]
|
(raise e))))]
|
||||||
(fn
|
{:name ::exception
|
||||||
([request]
|
:wrap (fn [handler]
|
||||||
(try
|
(fn
|
||||||
(handler request)
|
([request]
|
||||||
(catch Throwable e
|
(try
|
||||||
(on-exception e request identity #(throw %)))))
|
(handler request)
|
||||||
([request respond raise]
|
(catch Throwable e
|
||||||
(try
|
(on-exception e request identity #(throw %)))))
|
||||||
(handler request respond (fn [e] (on-exception e request respond raise)))
|
([request respond raise]
|
||||||
(catch Throwable e
|
(try
|
||||||
(on-exception e request respond raise))))))))
|
(handler request respond (fn [e] (on-exception e request respond raise)))
|
||||||
|
(catch Throwable e
|
||||||
|
(on-exception e request respond raise))))))})))
|
||||||
|
|
|
||||||
100
test/clj/reitit/ring/middleware/exception_test.clj
Normal file
100
test/clj/reitit/ring/middleware/exception_test.clj
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
(ns reitit.ring.middleware.exception-test
|
||||||
|
(:require [clojure.test :refer [deftest testing is]]
|
||||||
|
[reitit.ring :as ring]
|
||||||
|
[reitit.ring.middleware.exception :as exception]
|
||||||
|
[reitit.coercion.spec]
|
||||||
|
[reitit.ring.coercion]
|
||||||
|
[muuntaja.core :as m])
|
||||||
|
(:import (java.sql SQLException SQLWarning)))
|
||||||
|
|
||||||
|
(derive ::kikka ::kukka)
|
||||||
|
|
||||||
|
(deftest exception-test
|
||||||
|
(letfn [(create [f]
|
||||||
|
(ring/ring-handler
|
||||||
|
(ring/router
|
||||||
|
[["/defaults"
|
||||||
|
{:handler f}]
|
||||||
|
["/coercion"
|
||||||
|
{:middleware [reitit.ring.coercion/coerce-request-middleware
|
||||||
|
reitit.ring.coercion/coerce-response-middleware]
|
||||||
|
:coercion reitit.coercion.spec/coercion
|
||||||
|
:parameters {:query {:x int?, :y int?}}
|
||||||
|
:responses {200 {:body {:total pos-int?}}}
|
||||||
|
:handler f}]]
|
||||||
|
{:data {:middleware [(exception/create-exceptions-middleware
|
||||||
|
(merge
|
||||||
|
exception/default-options
|
||||||
|
{::kikka (constantly {:status 200, :body "kikka"})
|
||||||
|
SQLException (constantly {:status 200, :body "sql"})}))]}})))]
|
||||||
|
|
||||||
|
(testing "normal calls work ok"
|
||||||
|
(let [response {:status 200, :body "ok"}
|
||||||
|
app (create (fn [_] response))]
|
||||||
|
(is (= response (app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing "unknown exception"
|
||||||
|
(let [app (create (fn [_] (throw (NullPointerException.))))]
|
||||||
|
(is (= {:status 500
|
||||||
|
:body {:type "exception"
|
||||||
|
:class "java.lang.NullPointerException"}}
|
||||||
|
(app {:request-method :get, :uri "/defaults"}))))
|
||||||
|
(let [app (create (fn [_] (throw (ex-info "fail" {:type ::invalid}))))]
|
||||||
|
(is (= {:status 500
|
||||||
|
:body {:type "exception"
|
||||||
|
:class "clojure.lang.ExceptionInfo"}}
|
||||||
|
(app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing "::ring/response"
|
||||||
|
(let [response {:status 200, :body "ok"}
|
||||||
|
app (create (fn [_] (throw (ex-info "fail" {:type ::ring/response, :response response}))))]
|
||||||
|
(is (= response (app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing ":muuntaja/decode"
|
||||||
|
(let [app (create (fn [_] (m/decode m/instance "application/json" "{:so \"invalid\"}")))]
|
||||||
|
(is (= {:body "Malformed \"application/json\" request."
|
||||||
|
:headers {"Content-Type" "text/plain"}
|
||||||
|
:status 400}
|
||||||
|
(app {:request-method :get, :uri "/defaults"}))))
|
||||||
|
|
||||||
|
(testing "::coercion/request-coercion"
|
||||||
|
(let [app (create (fn [{{{:keys [x y]} :query} :parameters}]
|
||||||
|
{:status 200, :body {:total (+ x y)}}))]
|
||||||
|
|
||||||
|
(let [{:keys [status body]} (app {:request-method :get
|
||||||
|
:uri "/coercion"
|
||||||
|
:query-params {"x" "1", "y" "2"}})]
|
||||||
|
(is (= 200 status))
|
||||||
|
(is (= {:total 3} body)))
|
||||||
|
|
||||||
|
(let [{:keys [status body]} (app {:request-method :get
|
||||||
|
:uri "/coercion"
|
||||||
|
:query-params {"x" "abba", "y" "2"}})]
|
||||||
|
(is (= 400 status))
|
||||||
|
(is (= :reitit.coercion/request-coercion (:type body))))
|
||||||
|
|
||||||
|
(let [{:keys [status body]} (app {:request-method :get
|
||||||
|
:uri "/coercion"
|
||||||
|
:query-params {"x" "-10", "y" "2"}})]
|
||||||
|
(is (= 500 status))
|
||||||
|
(is (= :reitit.coercion/response-coercion (:type body)))))))
|
||||||
|
|
||||||
|
(testing "exact :type"
|
||||||
|
(let [app (create (fn [_] (throw (ex-info "fail" {:type ::kikka}))))]
|
||||||
|
(is (= {:status 200, :body "kikka"}
|
||||||
|
(app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing "parent :type"
|
||||||
|
(let [app (create (fn [_] (throw (ex-info "fail" {:type ::kukka}))))]
|
||||||
|
(is (= {:status 200, :body "kikka"}
|
||||||
|
(app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing "exact Exception"
|
||||||
|
(let [app (create (fn [_] (throw (SQLException.))))]
|
||||||
|
(is (= {:status 200, :body "sql"}
|
||||||
|
(app {:request-method :get, :uri "/defaults"})))))
|
||||||
|
|
||||||
|
(testing "Exception SuperClass"
|
||||||
|
(let [app (create (fn [_] (throw (SQLWarning.))))]
|
||||||
|
(is (= {:status 200, :body "sql"}
|
||||||
|
(app {:request-method :get, :uri "/defaults"})))))))
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
(:require [clojure.test :refer [deftest testing is]]
|
(:require [clojure.test :refer [deftest testing is]]
|
||||||
[reitit.ring :as ring]
|
[reitit.ring :as ring]
|
||||||
[reitit.ring.middleware.muuntaja :as muuntaja]
|
[reitit.ring.middleware.muuntaja :as muuntaja]
|
||||||
[muuntaja.core :as m]
|
|
||||||
[reitit.swagger :as swagger]
|
[reitit.swagger :as swagger]
|
||||||
[reitit.core :as r]))
|
[muuntaja.core :as m]))
|
||||||
|
|
||||||
(deftest muuntaja-test
|
(deftest muuntaja-test
|
||||||
(let [data {:kikka "kukka"}
|
(let [data {:kikka "kukka"}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue