Search code examples
node.jsgoogle-chromeexpresscors

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


Solution

  • So it turns out that because I had both nginx and express set up to respond with headers to the options request, it was somehow combining the Access-Control-Allow-Origin header value into "", "". I don't know if it read that as an array or what.

    Still pretty baffled because 1) Why did the request make it past nginx? and 2) Why did the browser proceed with the POST if the OPTIONS headers were messed up?

    Oh well, the lesson, as always -- Don't Repeat Yourself.