Fork me on GitHub
#pedestal
<
2019-02-15
>
caleb.macdonaldblack02:02:23

500 errors/exceptions don't seem to add the cors header using ::http/allowed-origins. All other requests do. Is there any way to add this without creating an error interceptor to repeat what the ::http/allowed-origins param does. Or something else wrong here?

ddeaguiar15:02:02

@caleb.macdonaldblack while Pedestal provides default error handling, I’d recommend implementing your own error handling interceptor which associates a more informative and, possibly, context-specific response. Adding such an error handling interceptor to your common interceptor collection will create a response which will be returns with the relevant CORS headers.

ddeaguiar15:02:47

Here are some more details: Default error handling is considered last resort and is interceptor chain provider specific. The servlet interceptor chain provider provides a catchall but it’s implemented within the internal response processing logic. CORS is implemented as an interceptor and only supports the :enter and :leave keys. On :leave it merges the relevant headers to the response :headers map. There is no :error support because, what should it do in the case of an error? This is an application-specific concern. Explicitly handle your errors and you’ll get the result you are looking for.

ddeaguiar15:02:46

BTW, when I talked about context-specific error handling, I was referring to the error-dispatch helper provided by Pedestal (https://github.com/pedestal/pedestal/blob/master/interceptor/src/io/pedestal/interceptor/error.clj#L17).

ddeaguiar15:02:31

It allows you to provide both general and specific error handling in one place

caleb.macdonaldblack15:02:48

Thank you for for your response. I left my question up to see if there were any other solutions. I did end up using error-dispatch though which is exactly what I needed

ddeaguiar21:02:56

I just added a Unit Testing reference to the http://pedestal.io site (http://pedestal.io/reference/unit-testing). @ariel.silverman you may find it useful.

👍 20
asilverman00:02:17

Thank you so much, I tried this approach but in my case since our service is wrapped inside a component I ended up creating a macro I am using as a fixture to exercise the response-for function

(defmacro with-mock-ds-system
  [[sym ds-factory] & body]
  ;; Create a system map with a mock datastore and a mock auth-checker, set ::http/join == false so
  ;; that the system doesn't block execution.
  `(let [temp# ~ds-factory]
     ;; Store a reference to this system, perhaps unnecessary but done for the sake
     ;; of future debuggability.
     (reset! mock-svc (component/start-system (service/consent-service
                                                (env/get-api-config)
                                                (create-mock-auth-checker (env/get-api-config))
                                                {:type   :mockstore
                                                 :config temp#}
                                                {:env         :dev
                                                 ::http/join? false})))
     ;; Pull the servlet function that is used for testing out of the newly created system.
     (let [~sym (get-in @mock-svc [:consent :service ::http/service-fn])]
       (try
         ~@body
         ;; Shutdown system.
         (finally
           (component/stop-system @mock-svc)
           (reset! mock-svc nil))))))

ddeaguiar16:02:37

@ariel.silverman, :thumbsup:. I’ve done something similar in the past but leveraged a fixture.

asilverman16:02:21

I also had a fixture implementation but ended up abandoning that approach because I want to dynamically change behavior of the mock datastore based on test specific scenarios and realized that fixtures do not allow for arguments and it just seemed a bit clunky.

asilverman16:02:45

thank you for your help and for taking the initiative to write a guide on pedestal on testing. 🙂