-
Notifications
You must be signed in to change notification settings - Fork 149
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 first match of:
- exception
ex-data
key:type
- exception class
- exception parent classes
If none of the above matches, :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:
(require '[compojure.api.exception :as ex])
(require '[ring.util.http-response :as response])
(defn custom-handler [f type]
(fn [^Exception e data request]
(f {:message (.getMessage e), :type type})))
(api
{:exceptions
{:handlers
{;; catches ex-infos with {:type ::calm}
::calm (custom-handler response/enhance-your-calm :calm)
;; catches all SQLExceptions (and it's subclasses)
java.sql.SQLException (custom-handler response/internal-server-error :sql)
;; log all request validation errors
::ex/request-validation (ex/with-logging ex/request-validation-handler :info)
;; everything else
::ex/default (custom-handler response/internal-server-error :unknown)}}}
...)
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
:
(api
{: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.