-
Notifications
You must be signed in to change notification settings - Fork 147
Exception handling
All exceptions should be handled gracefully. Compojure-api ships with customizable exception handling with working
defaults. Customization is done via api or api-middleware options - which delegate actual processing to compojure.api.middleware/wrap-exceptions doing the actual work. It catches all thrown exceptions and selects a custom handler based on the thrown exception ex-data or Slingshot value of key :type. If an exception doesn't have ex-data (e.g. legacy Java Exceptions), :compojure.api.exception/default type is used. Exception handlers are 3-arity functions, getting the exception,
ex-data and request as arguments. Below are the default type definitions and default handling:
| type | what | default |
|---|---|---|
:compojure.api.exception/request-parsing |
Input data de-serialization errors. | 400 + error in body |
:compojure.api.exception/request-validation |
Request Schema coercion errors. | 400 + schema error in body |
:compojure.api.exception/response-validation |
Response Schema coercion errors. | 500 + schema error in body |
:compojure.api.exception/default |
Everything else. | 500 + print stacktrace + safe message |
example to override the default case + add a custom exception type + handler for it:
(defn custom-handler [^Exception e data request]
(internal-server-error {:message (.getMessage e)}))
(defn calm-handler [^Exception e data request]
(enhance-your-calm {:message (.getMessage e), :data data}))
(defapi
{:exceptions {:handlers {:compojure.api.exception/default custom-handler
::calm calm-handler}}}
(GET "/bang" [] (throw (RuntimeException. "kosh")))
(GET "/calm" [] (throw (ex-info "fail" {:type ::calm, :oil "snake"}))))By default only :compojure.api.exception/default handler logs the messages. Since 0.24.5, to add logging to other default handlers you can use function compojure.api.exception/with-logging:
(defapi
{:exceptions {:handlers {::ex/request-parsing (ex/with-logging ex/request-parsing-handler :info)
::ex/response-validation (ex/with-logging ex/response-validation-handler :error)}}}
(POST "/bang" [] (ok)))with-logging just wraps the given handler function and calls simple logging function before calling the handler. The function takes optional second argument to set the log level for messages, this is useful to mark e.g. request parsing errors caused by bad clients less important. To control what is logged create your own handlers or own logging wrapper.