Skip to content

Instantly share code, notes, and snippets.

@borkdude
Created January 17, 2019 13:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borkdude/441379ec59d8da7f72348453ee15f32a to your computer and use it in GitHub Desktop.
Save borkdude/441379ec59d8da7f72348453ee15f32a to your computer and use it in GitHub Desktop.
Yada error handling
(ns app.yada.error-renderers
"Yada error renderer overrides"
{:authors ["Michiel Borkent"]}
(:require ...
...
...
[reloaded.repl :as rr]
[selmer.parser :as parser]
[taoensso.timbre :refer [debug info error warn]]
[yada.body :as body :refer [render-error get-error-message]]
[yada.charset :as charset]
[yada.handler :as handler] ;; load because of interning
[yada.schema :as ys :refer [resource-coercer]]))
;; Note: @malcolmsparks recommended the following for adding application/json error handling
;; > For now, you can replace with your own error interceptor chain
;; > It is a bit arduous but worthwhile because you're then in complete control of error handling.
;; https://clojurians.slack.com/archives/C0702A7SB/p1493735777665719
;; But this also works. Maybe if we get into more issues, we'll try our own error interceptor chain.
;; See https://github.com/juxt/yada/blob/5d49342bcb994309b96673fb4a531ff313647c79/src/yada/handler.clj#L52
(intern 'yada.handler 'error-representations
(ys/representation-seq
(ys/representation-set-coercer
[{:media-type #{"application/json"
"application/transit+json"
"application/json;pretty=true;q=0.96"
"text/plain;q=0.9"
"text/html;q=0.8"
"application/edn;q=0.6"
"application/edn;pretty=true;q=0.5"}
:charset charset/platform-charsets}])))
...
(defn define-error-renderers [dev-env?]
;; See https://github.com/juxt/yada/blob/master/src/yada/body.clj#L214
(defmethod render-error "text/html"
[status ^Throwable error representation {:keys [id options] :as m}]
(parser/render-file
"error.html"
{:status status
:message (format "%d: %s" status (body/get-error-message status))
:description (body/get-error-description status)
:exception (when dev-env?
(let [baos (java.io.ByteArrayOutputStream.)
pw (java.io.PrintWriter.
(java.io.OutputStreamWriter. baos))]
(.printStackTrace error pw)
(.flush pw)
(String. (.toByteArray baos))))}))
(defn api-error-renderer [status error representation
{:keys [id options method request]}]
(if error ;; no error is provided with 404, etc.
(let [error (unnest-exception error)]
(or (and (= 400 status)
(let [maybe-error (:error (ex-data error))
maybe-error (when (map? maybe-error)
(not-empty maybe-error))]
(and maybe-error
{:error maybe-error
:message "Schema validation error"})))
(let [exception-data (ex-data error)
exception-type (:type exception-data)
error-response
(if-let [message (get error-messages exception-type)]
(error/error message error)
(case exception-type
...
exception-data
;; Fallback
(do
(when exception-type
(warn "Uncaught exception-type" exception-type))
(error/error error))))
error-response
(if-not dev-env?
(dissoc error-response :details)
error-response)
response (not-empty
(nn-hash-map :error (not-empty error-response)))]
response)))
(info "Responding with" status "on request"
(select-keys request [:uri :params]))))
;; See https://github.com/juxt/yada/blob/master/src/yada/body.clj#L252
(defmethod render-error "application/json"
[status error representation ctx]
(api-error-renderer status error representation ctx))
;; See https://github.com/juxt/yada/blob/master/src/yada/body.clj#L261
(defmethod render-error "application/transit+json"
[status error representation ctx]
(api-error-renderer status error representation ctx)))
;;;; Scratch
(comment
(rr/reset)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment