Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS: preflight passes, main request completes w/200, but browser still has Origin error

I am sending a CORS ajax request to a node server running express. In both the server logs and the js console, I can see that the preflight OPTIONS request succeeds.

Then, the main request also succeeds on the server and responds with a 200 and what I think are the correct headers. However, in Chrome, the networking tab reports the latter request as "cancelled" and the response is not accepted or processed:

XMLHttpRequest cannot load http://myserver.com/upload. Origin http://mysite.com is not allowed by Access-Control-Allow-Origin.

Here are the server logs with the headers printed out for both requests and responses:

76.79.201.210 - - [27/Jun/2013:23:23:17 +0000] "OPTIONS /upload HTTP/1.1" 204 0 "http://mysite.com/add" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"
START
{ host: 'localhost:5001',
  connection: 'close',
  'content-length': '109587',
  origin: 'http://mysite.com',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36',
  'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryBZA4TATeeVWMHArH',
  accept: '*/*',
  referer: 'http://mysite.com/add',
  'accept-encoding': 'gzip,deflate,sdch',
  'accept-language': 'en-US,en;q=0.8' }
{ 'x-powered-by': 'Express',
  'access-control-allow-origin': '*',
  'access-control-allow-methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'access-control-allow-headers': 'X-Requested-With' }
XX.XX.XXX.210 - - [27/Jun/2013:23:23:19 +0000] "POST /upload HTTP/1.1" 200 118 "http://mysite.com/add" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"
- - - [Thu, 27 Jun 2013 23:23:19 GMT] "POST /upload HTTP/1.0" 200 - "http://mysite.com/add" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36"

Update: screenshot from Chrome's network tab -- the "cancelled" one is the one that was a 200 above

http://cl.ly/image/3c09330i1a17

like image 288
Jeremy Raines Avatar asked Jun 27 '13 23:06

Jeremy Raines


People also ask

What HTTP method is used for pre flight CORS request?

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers. It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method , Access-Control-Request-Headers , and the Origin header.

How does a CORS preflight work?

CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.


1 Answers

Troubleshooting CORS-Related Problems

  • If you are trying to reproduce the problem, and you're not seeing a request/response, it is possible that your browser has cached an earlier failed preflight request attempt. Clearing your browser's cache may also clear the preflight cache...

https://developers.google.com/storage/docs/cross-origin

I tested the following configuration on test-cors.org and it appears to work. Just remember to clear your cache every now and then while you are troubleshooting.

var allowedHost = {
    // this is the origin that test-cors.org uses
    'http://client.cors-api.appspot.com': true
};

var allowCrossDomain = function(req, res, next) {
    if (!req.headers.origin || allowedHost[req.headers.origin]) {
        res.header('Access-Control-Allow-Credentials', true);
        res.header('Access-Control-Allow-Origin', req.headers.origin)
        res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
        res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
        if (req.method == 'OPTIONS') res.send(200);
        else next();
    }
    else {
        res.send(403, {
            auth: false
        });
    }
}

Good luck!

like image 127
Brian Lewis Avatar answered Sep 17 '22 09:09

Brian Lewis