Benjamin McFerren
Benjamin McFerren

Reputation: 862

Angular POST to Clojure Ring receivesResponse for preflight has invalid HTTP status code 404

I am working to overcome cors issues with my Angular / Clojure app and I am having trouble unerstanding what syntax to use in order to avoid the Access-Control-Allow-Origin error for POST and GET requests

I have added this code to my clojure controller where my routes are found and it seems to fix the issue for GET requests:

(POST "/node/create" request
    (let [node_object (or (get-in request [:params :data])
                          (get-in request [:body :data])
                          "ROUTER_ERROR")]
      {:status 200
       :headers {"Content-Type" "application/json"}
       :body (recursiftion.model/createNode node_object)
      }
))

(defn allow-cross-origin  
  "middleware function to allow crosss origin"  
  [handler]  
  (fn [request]  
   (let [response (handler request)]  
    (assoc-in response [:headers "Access-Control-Allow-Origin"]  
         "*"))))

(def app
 (-> (handler/api app-routes)
      (middleware/wrap-json-body {:keywords? true})
      (middleware/wrap-json-response)
      (allow-cross-origin)))

And this Angular code

this.post = function (object) { 

    console.log('BANG', object);

    return $http({
                method: "post",
                url: "https://mywebserveraddress.com/node/create",
                data: object
            }); 
    };

But I still have related errors for my POST requests:

preflight has invalid HTTP status code 404

I am looking for the right syntax to add to my clojure application in order for me to make cross domain ajax requests from my angular spa that will live on localhost for development and external servers from my production environment.

I am very grateful for help you can give.

Upvotes: 0

Views: 686

Answers (1)

xsc
xsc

Reputation: 6073

CORS requires non-GET requests to send a so-called "preflight" requests, using the OPTIONS method. Your code returns 404 because their is no handler for (OPTIONS "/node/create" ...).

A better - but still very much not complete - CORS middleware would be shaped like:

(def ^:private cors-headers
  {"access-control-..." ...})

(defn wrap-cors
  [handler]
  (fn [request]
    (some-> (if (= (:request-method request) :options)
              {:status 200}
              (handler request))
            (update :headers merge cors-headers))))

But there are more intricacies (like * not being a valid value for Access-Control-Allow-Origin in some cases), so I'd recommend to go with an already existing library, e.g. ring-cors or ring.middleware.cors, to take care of them.

Upvotes: 1

Related Questions