Skip to content

Commit cf81b42

Browse files
committed
README for exceptions
1 parent 800d0b7 commit cf81b42

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ There is prepackaged middleware `compojure.api.middleware/api-middleware` for co
139139

140140
- catching slingshotted http-errors (`ring.middleware.http-response/catch-response`)
141141
- catching model validation errors (`ring.swagger.middleware/catch-validation-errors`)
142-
- catching unhandler exceptions (`compojure.api.middleware/wrap-exceptions`)
142+
- catching unhandled exceptions (`compojure.api.middleware/wrap-exceptions`)
143143
- support for different protocols via `ring.middleware.format-params/wrap-restful-params` and `ring.middleware.format-response/wrap-restful-response`
144144
- default supported protocols are: `:json-kw`, `:yaml-kw`, `:edn`, `:transit-json` and `:transit-msgpack`
145145
- enabled protocol support is also published into Swagger docs via `ring.swagger.middleware/wrap-swagger-data`.
@@ -433,6 +433,38 @@ the `:components` restucturing with letk-syntax.
433433

434434
To see this in action, try `lein run` and navigate to Components api group.
435435

436+
## Exception handling
437+
438+
All exceptions should be handled gracefully. Compojure-api ships with customizable exception handling with good
439+
defaults. Customization is done via `api` options - delegating to `compojure.api.middleware/wrap-exceptions`, which
440+
does the real work. It catches all thrown exceptions and selects a custom handler based on the thrown exception
441+
`ex-data` value of key `:type`. If an exception doesn't have ex-data (e.g. legacy Java Exceptions),
442+
`:compojure.api.exception/default` type is used. Exception handlers are 3-arity functions, getting the exception,
443+
ex-data and request as arguments. Below are the default type definitions and default handling:
444+
445+
| type | what | default
446+
|-----------------------------------------------|-------------------------------------|---------
447+
|`:compojure.api.exception/request-parsing` | Input data de-serialization errors. | 400 + error in body
448+
|`:compojure.api.exception/request-validation` | Request Schema coercion errors. | 400 + schema error in body
449+
|`:compojure.api.exception/response-validation` | Response Schema coercion errors. | 500 + schema error in body
450+
|`:compojure.api.exception/default` | Everything else. | 500 + print stacktrace + safe message
451+
452+
example to override the default case + add a custom exception type + handler for it:
453+
454+
```clojure
455+
(defn custom-handler [^Exception e data request]
456+
(internal-server-error {:message (.getMessage e)}))
457+
458+
(defn calm-handler [^Exception e data request]
459+
(enhance-your-calm {:message (.getMessage e), :data data}))
460+
461+
(defapi
462+
{:exceptions {:handlers {:compojure.api.exception/default custom-handler
463+
::calm calm-handler}}}
464+
(GET* "/bang" [] (throw (RuntimeException. "kosh")))
465+
(GET* "/calm" [] (throw (ex-info "fail" {:type ::calm, :oil "snake"}))))
466+
```
467+
436468
## Schemas
437469

438470
Compojure-api uses the [Schema](https://github.com/Prismatic/schema) to describe data models, backed up by

src/compojure/api/exception.clj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
Error response only contains class of the Exception so that it won't accidentally
1717
expose secret details."
18-
[^Exception e data request]
18+
[^Exception e _ _]
1919
(.printStackTrace e)
2020
(internal-server-error {:type "unknown-exception"
2121
:class (.getName (.getClass e))}))
@@ -33,22 +33,22 @@
3333

3434
(defn response-validation-handler
3535
"Creates error response based on Schema error."
36-
[_ data request]
36+
[_ data _]
3737
(internal-server-error {:errors (stringify-error (su/error-val data))}))
3838

3939
(defn request-validation-handler
4040
"Creates error response based on Schema error."
41-
[_ data request]
41+
[_ data _]
4242
(bad-request {:errors (stringify-error (su/error-val data))}))
4343

4444
(defn schema-error-handler
4545
"Creates error response based on Schema error."
46-
[ex data request]
46+
[_ data _]
4747
; FIXME: Why error is not wrapped to ErrorContainer here?
4848
(bad-request {:errors (stringify-error (:error data))}))
4949

5050
(defn request-parsing-handler
51-
[^Exception ex data request]
51+
[^Exception ex _ _]
5252
(let [cause (.getCause ex)]
5353
(bad-request {:type (cond
5454
(instance? JsonParseException cause) "json-parse-exception"

0 commit comments

Comments
 (0)