Search code examples
jquerynode.jsfirefoxwebkithttp-status-code-502

jQuery not sending a custom headers CORS request to node.js server, or server not receiving?


I've been struggling with this one for a whole weekend. The problem exists only when accessed through mac computers and when hosted through my nodejitsu instance, and doesn't exist on my localhost server.

My application is quite typical. It has a web server component and REST server on a different domain --hence the need for CORS. Only added complexity is custom headers.

I've set up CORS on my node.js server as follows

var allowCrossDomain = function(req, res, next) {

    console.log(req.headers);

    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Accept, X-api-key, X-auth-token, Content-Type, Content-Length');

    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Headers', 'Accept, X-api-key, X-auth-token, Content-Type, Content-Length');
        res.send(200, {});
    }
    else {
      next();
    }
};

The frontend $.ajax call is like this

//create user
$.ajax({
    url: host + 'users',
    headers: {'X-api-key': apikey},
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    data: JSON.stringify({
        email: userInfo.email,
        username: username,
        password: pasword,
    }),
    xhrFields: {},
    crossDomain: true,
    success: function (res) {
        console.log(res);
        $('.messages')
            .removeClass('error')
            .addClass('success')
            .html('<strong>Success! </strong>Check email for activation link');
    },
    error: function (xhr, status, errorThrown) {
        console.log(xhr.responseText);
        var errorMessage = $.parseJSON(xhr.responseText);
        $('.messages')
            .removeClass('success')
            .addClass('error')
            .html('<strong>Oops!</strong> '+errorMessage.error);

    }
});

Techincally this should work. It's a textbook ajax call to a node server, but when I make the call in chrome, I get the following error pre-preflight in chrome terminal.


    OPTIONS http://api.dev.XXXXX.com/users/login net::ERR_EMPTY_RESPONSE
    jquery-1.7.2.js:8240
    send jquery-1.7.2.js:8240
    jQuery.extend.ajax jquery-1.7.2.js:7719
    (anonymous function) VM62:2
    InjectedScript._evaluateOn VM57:730
    InjectedScript._evaluateAndWrap VM57:669
    InjectedScript.evaluate

On firefox/mozilla it's this and on Safari it's quite similar:


    "NetworkError: 502 Bad Gateway - http://api.dev.XXXX.com/users/fbauth"
    fbauth
    Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://api.dev.XXXX.com/users/fbauth. This can be fixed by moving the resource to the same domain or enabling CORS.

I've somehow managed to partially bypass this by preceding the complex HTTP request simple HTTP request to the server. I don't know why this makes it work, which makes it the world's ugliest, and most partially effective hack.

  $(document).ready(function(){
    setTimeout(function(){
    $.ajax({
      url: host + 'users/login',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify({

      })
    });

    $.ajax({
      url: host + 'users/fbauth',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify({

      })
    });

    }, 500);
  })

Issue now is that a preflight HAS to be performed almost immediately after doing the simple HTTP, and as a result, oauth with fb login doesn't work, since it does a few requests to fb and back before doing what it needs to do.

I'm totally stuck here. Is this a webkit/mozilla engine issue? Or am I missing something critical here?

Here's a jsfiddle with an example request to a test endpoint. Check console while running. http://jsfiddle.net/cvince/6nPLJ/

ISSUE-- Fails on my main dev machine, but it might be working for you. The request preflights and validates properly on 4 of my 6 computers.


Solution

  • Turned out to be caused by my VPN client. Fringe case! This is the solution: http://www.bennadel.com/blog/2559-cisco-anyconnect-vpn-client-may-block-cors-ajax-options-requests.htm