1

I am trying to send a CORS request using AJAX to a nodeJS server. I want to return some JSON data. I've found numerous tutorials online that all say the same thing, which I've tried, but I can't get this to work. Here's the AJAX request:

$.ajax({
        url: "http://some.other.url.com:8880",
        type: "GET",
        crossDomain: true,
        contentType: 'application/json'
    }).then(function(response) {
        $scope.allData = jQuery.parseJSON( response );
        console.log($scope.allData);
    }).fail(function(response) {
});

And here is the code on the server:

var path = url.parse(req.url).pathname,
    match = router.match(path),
    rescode;

    console.log("---: " + req.method);

if (req.method === 'OPTIONS') {
    var headers = {};
    headers["Access-Control-Allow-Origin"] = "*";
    headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
    headers["Access-Control-Allow-Credentials"] = false;
    headers["Access-Control-Max-Age"] = '86400'; // 24 hours
    headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
    res.writeHead(200, headers);
    return res.end();
}

I'v also tried it without the return on res.end() i.e. not returning the OPTIONS preflight request, and that doesn't work either.

--Edit-- Here is the actual error message in the console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://other.domain.com:8880/. This can be fixed by moving the resource to the same domain or enabling CORS.

The server is getting the requests. Both the OPTIONS and then GET requests are hitting the server and being responded to. In fact, in the console log for the page making the AJAX request, I can click on the CORS error and see the response, and it is the correct data. But I can't seem to get the javascript to continue.

In regards to .done vs .then, they seem to work interchangeable. Or at least, in this example, the .then and .fail are working just fine.

apsillers
  • 112,806
  • 17
  • 235
  • 239
Trevor
  • 995
  • 3
  • 10
  • 25
  • So what does the browser say when you look at its error console? Cross-origin requests on different ports are generally forbidden, so I'm pretty sure it'll tell you there is a port mismatch. – Mike 'Pomax' Kamermans Sep 02 '14 at 19:11
  • So you're sending CORS headers for the OPTIONS preflight. Are you sending CORS headers for the actual GET request? – apsillers Sep 02 '14 at 19:20
  • I'm pretty sure $.ajax returns to a 'done' promise instead of 'then'? Are you getting a response at all? Please provide more information about the error you're seeing. – Jasdeep Khalsa Sep 02 '14 at 19:22
  • Please point out exactly what's failing. Does the server ever see a GET request (i.e., does that `console.log("---: " + req.method)` ever output `---: GET`)? What error message do you see on the client? – apsillers Sep 02 '14 at 19:28
  • see my edit for responses to these questions – Trevor Sep 02 '14 at 19:44
  • @Trevor Could you show the code where you set/send CORS response headers for the GET request? You only show the CORS response headers you send for the OPTIONS preflight. From your description, it sounds like the preflight succeeds, the browser is allowed to attempt a GET request, and the GET response doesn't have the appropriate `Access-Control-Allow-Origin` on it. – apsillers Sep 02 '14 at 19:52
  • @apsillers Are you saying that I need to set those header options for both the OPTIONS preflight and the GET request itself? I was unaware of this... Do I set the headers the exact same way or need to add other things? – Trevor Sep 02 '14 at 20:25
  • [This answer](http://stackoverflow.com/questions/18310394/no-access-control-allow-origin-node-apache-port-issue) might help. – mccannf Sep 02 '14 at 21:11
  • @mccannf I'm not seeing what is different about that answer. I'm setting all of those same headers in my NodeJS code. Are you saying that I MUST use express to get this to function? I tried using the CORS express extension and had the same problems. – Trevor Sep 02 '14 at 21:29
  • @Trevor, I'm not if sure it solves your problem; however, the difference between the answer that mccannf linked and your code is that EACH request/response the server makes (GET or OPTIONS) has the CORS headers added. – ctlacko Sep 02 '14 at 21:43
  • @Trevor Yes, both the preflight and the actual response must include CORS headers. I'll draft an answer now with information about which headers must accompany each step. – apsillers Sep 02 '14 at 22:10

1 Answers1

2

You're correctly setting CORS headers in your OPTIONS preflight response, but you also need to set Access-Control-Allow-Origin (either to your origin or *) on your actual GET response. The GET response should respond with the same CORS headers, regardless of whether there was a preflight response or not. This means that it must send the appropriate CORS headers, but it does not need to send anything except for Access-Control-Allow-Origin. (If other non-simple components like non-simple verbs or headers are involved, they will be allowed or denied in the preflight; the actual GET response does not need to worry about them.)

The Enable CORS site has a CORS testing tool to help you see the headers involved in a request that you specify. I've used that tool to set up a test similar to your case (GET with non-simple Content-Type header). If we examine the results of that test (careful -- the steps are presented little bit out of order, but they're all there), we see a preflight response:

Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS
...
Access-Control-Allow-Origin: http://client.cors-api.appspot.com
Access-Control-Allow-Headers: X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept

And the final CORS response:

Content-Length: 0
Content-Type: application/json
Access-Control-Allow-Origin: http://client.cors-api.appspot.com
Cache-Control: no-cache

As you can see, the GET response also has a Access-Control-Allow-Origin header and no other CORS headers. If you have any further uncertainties, feel free to tweak the settings on that tool to run a wide range of other test cases.

apsillers
  • 112,806
  • 17
  • 235
  • 239
  • Finally! None of the tutorials or information I read online mentioned anything about including the headers for the GET request as well as the OPTIONS request. – Trevor Sep 03 '14 at 00:08