Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX error-interceptor-ctx keeps ctx state of non-erroring interceptor… #327

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 53 additions & 42 deletions src/yada/handler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -111,52 +111,63 @@
;; Normal resources
(->
(apply d/chain ctx (:interceptor-chain ctx))

(d/catch
java.lang.Exception
(fn [e]
(error-handler e)
(let [data (error-data e)]
(let [status (or (:status data) 500)]

(let [custom-response (get* (:responses resource) status)
rep (rep/select-best-representation
(:request ctx)
(if custom-response
(or (:produces custom-response) [{:media-type "text/plain"
:charset "UTF-8"}])
error-representations)
)]

(apply d/chain
(cond-> (or (:ctx data) ctx)
e (assoc :error e)
;; true (merge (select-keys ctx [:id :request :method]))
status (assoc-in [:response :status] status)
(:headers data) (assoc-in [:response :headers] (:headers data))

rep (assoc-in [:response :produces] rep)

;; This primes the body data in case the representation is nil
(contains? data :body)
(assoc-in [:response :body] (:body data))

(contains? data :cookies)
(assoc-in [:response :cookies] (:cookies data))

;; This could override [:response :body]
(and (not (contains? data :body)) (not (:response custom-response)))
(standard-error status e rep)

;; This could override [:response :body]
(and (not (contains? data :body)) (:response custom-response))
(custom-error (:response custom-response) rep)

true set-content-length)

(:error-interceptor-chain ctx)

))))))))))
(let [data (error-data e)
status (or (:status data) 500)
custom-response (get* (:responses resource) status)
;; create CTX that is based on interceptors before error
partial-ctx (d/loop [ctx ctx
[interceptor & interceptors-rest] (:interceptor-chain ctx)]
(let [next-ctx (interceptor ctx)]
(if (instance? manifold.deferred.ErrorDeferred next-ctx)
ctx
(d/recur next-ctx interceptors-rest))))
;; update ctx based on error cause, error, or non-erroring interceptors
ctx (or
(some->> e ex-cause ex-data :ctx) ;; ctx field via user made (throw (ex-info "..." {:ctx ctx}))
(:ctx data) ;; not sure if this is ever valid
@partial-ctx ;; get the last ctx that didn't fail an interceptor
;; initial ctx that request was made with, discard any :interceptor-chain changes
ctx)
rep (rep/select-best-representation
(:request ctx)
(if custom-response
(or (:produces custom-response) [{:media-type "text/plain"
:charset "UTF-8"}])
error-representations))
]
(apply d/chain
;; this is all to do with handling an error, we can put this in the error-interceptor-chain
(cond-> (or (:ctx data) ctx)
e (assoc :error e)
;; true (merge (select-keys ctx [:id :request :method]))
status (assoc-in [:response :status] status)
(:headers data) (assoc-in [:response :headers] (:headers data))

rep (assoc-in [:response :produces] rep)

;; This primes the body data in case the representation is nil
(contains? data :body)
(assoc-in [:response :body] (:body data))

(contains? data :cookies)
(assoc-in [:response :cookies] (:cookies data))

;;FIXME: This could override [:response :body]
(and (not (contains? data :body)) (not (:response custom-response)))
(standard-error ,, status e rep)

;;FIXME: This could override [:response :body]
;; this should be done in the error-interceptor-chain, because we lose access to the body
(and (not (contains? data :body)) (:response custom-response))
(custom-error ,, (:response custom-response) rep)

true (set-content-length ,,))

(:error-interceptor-chain ctx)))))))))

(defn handle-request
"Handle Ring request"
Expand Down