clojurecorscompojurecompojure-api

Can not execute middleware if using a exception handler?


wrap-cors does not return access control headers when there is a bad request against my api endpoint. I believe this is because I am using a exception handler which might be blocking the middleware from running. I want to know how I can still execute the middleware for this route and append the cors headers to the response of bad requests.

exception handler

(defn- bad-request-handler
  "Handles bad requests."
  [f]

  (f
    (ring/response {:status "bad request"})))

app

(def app
  (api
    {:exceptions {:handlers
                          {::ex/request-validation (bad-request-handler response/bad-request)}}}

    (POST "/" [] :body [item {(schema/required-key :item) schema/Bool}]
             :middleware [#(wrap-cors % :access-control-allow-origin [#".*"]
                                      :access-control-allow-methods [:post])]

             :responses {200 {:description "ok"}
                         400 {:description "bad request"}} item)))

Solution

  • I've decided to append my own headers rather than using r0man/ring-cors. I can determine the contents of the Access-Control-Allow-Methods by retrieving the :request-method value from the request. However, this makes the assumption that the bad request handler will only ever be called by valid routes.

    (defn- append-cors
      "Allow requests from all origins"
      [methods]
    
      {"Access-Control-Allow-Origin"  "*"
       "Access-Control-Allow-Methods" methods})
    
    
    (defn- bad-request-handler
      "Handles bad requests."
      [f]
    
      (fn [^Exception e data request]
        (->
          (f request)
          (update-in [:headers] merge (->
                                        (request :request-method)
                                        (name)
                                        (clojure.string/upper-case)
                                        (append-cors)))
          (assoc :body {:status "bad request"}))))
    

    I'm still not really sure why the cors headers are only added when the request is allowed.