Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability for interceptors to handle exceptions in lacinia
This change enables the use of standard pedestal error handling for errors raised in the interceptor stack or in lacinia itself. It does so by moving response error generation to the very end of the (outbound) interceptor stack. End users can then inject interceptors prior to it to handle or log exceptions as desired. As it stands, this is only applicable to the synchronous query executor. I would also like to invoke the same error interceptors with exceptions occurring on the asynchronous path, but am currently unable to figure out how exceptions occurriing in channels should be handled in pedestal. If we do figure that out, we can simplify some of the code here as there are now two error paths (one for sync, one for async).
- Loading branch information
1 parent
a6653f7
commit 2624f09
Showing
2 changed files
with
110 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
; Copyright (c) 2017-present Walmart, Inc. | ||
; | ||
; Licensed under the Apache License, Version 2.0 (the "License") | ||
; you may not use this file except in compliance with the License. | ||
; You may obtain a copy of the License at | ||
; | ||
; http://www.apache.org/licenses/LICENSE-2.0 | ||
; | ||
; Unless required by applicable law or agreed to in writing, software | ||
; distributed under the License is distributed on an "AS IS" BASIS, | ||
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
; See the License for the specific language governing permissions and | ||
; limitations under the License. | ||
|
||
(ns com.walmartlabs.lacinia.pedestal-error-test | ||
(:require | ||
[clojure.test :refer [deftest is use-fixtures]] | ||
[com.walmartlabs.lacinia.pedestal :refer [default-interceptors inject] :as lp] | ||
[com.walmartlabs.lacinia.test-utils :refer [test-server-fixture | ||
send-request]] | ||
[clojure.spec.test.alpha :as stest] | ||
[io.pedestal.interceptor :refer [interceptor]])) | ||
|
||
(stest/instrument) | ||
|
||
(defn proof-interceptor | ||
"Interceptor that records how often its error function is called" | ||
[proof] | ||
(interceptor | ||
{:name ::proof | ||
:error (fn [_ ex] | ||
(swap! proof inc) | ||
(throw ex))})) | ||
|
||
(def prior-error-proof (atom 0)) | ||
(def post-error-proof (atom 0)) | ||
|
||
(use-fixtures :once (test-server-fixture {:graphiql true} | ||
(fn [schema] | ||
{:interceptors (-> (default-interceptors schema {}) | ||
;; Should not be called | ||
(inject (proof-interceptor prior-error-proof) | ||
:before ::lp/error-response) | ||
;; Should be called | ||
(inject (proof-interceptor post-error-proof) | ||
:after ::lp/error-response))}))) | ||
|
||
(deftest can-return-failure-response | ||
(let [response (send-request "{ fail }")] | ||
(is (= {:body {:errors [{:message "resolver exception"}]} | ||
:status 500} | ||
(select-keys response [:status :body]))))) | ||
|
||
(deftest calls-post-error-interceptor | ||
(reset! prior-error-proof 0) | ||
(reset! post-error-proof 0) | ||
(send-request "{ fail }") | ||
(is (= 1 @post-error-proof))) | ||
|
||
(deftest skips-prior-error-interceptor | ||
(reset! prior-error-proof 0) | ||
(reset! post-error-proof 0) | ||
(send-request "{ fail }") | ||
(is (= 0 @prior-error-proof))) | ||
|