AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?

JqueryAjaxCross Domain

Jquery Problem Overview


I am working on an internal web application at work. In IE10 the requests work fine, but in Chrome all the AJAX requests (which there are many) are sent using OPTIONS instead of whatever defined method I give it. Technically my requests are "cross domain." The site is served on localhost:6120 and the service I'm making AJAX requests to is on 57124. This closed jquery bug defines the issue, but not a real fix.

What can I do to use the proper http method in ajax requests?

Edit:

This is in the document load of every page:

jQuery.support.cors = true;

And every AJAX is built similarly:

var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
    url: url,
    dataType: "json",
    data: json,
    async: true,
    cache: false,
    timeout: 30000,
    headers: { "x-li-format": "json", "X-UserName": userName },
    success: function (data) {
        // my success stuff
    },
    error: function (request, status, error) {
        // my error stuff
    },
    type: "POST"
});

Jquery Solutions


Solution 1 - Jquery

Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is why the jQuery bug was closed as won't-fix. This is by design.

> Unlike simple requests (discussed above), "preflighted" requests first > send an HTTP request by the OPTIONS method to the resource on the > other domain, in order to determine whether the actual request is safe > to send. Cross-site requests are preflighted like this since they may > have implications to user data. In particular, a request is > preflighted if: > > * It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than > application/x-www-form-urlencoded, multipart/form-data, or text/plain, > e.g. if the POST request sends an XML payload to the server using > application/xml or text/xml, then the request is preflighted. > * It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

Solution 2 - Jquery

Based on the fact that the request isn't sent on the default port 80/443 this Ajax call is automatically considered a cross-origin resource (CORS) request, which in other words means that the request automatically issues an OPTIONS request which checks for CORS headers on the server's/servlet's side.

This happens even if you set

crossOrigin: false;

or even if you ommit it.

The reason is simply that localhost != localhost:57124. Try sending it only to localhost without the port - it will fail, because the requested target won't be reachable, however notice that if the domain names are equal the request is sent without the OPTIONS request before POST.

Solution 3 - Jquery

I agree with Kevin B, the bug report says it all. It sounds like you are trying to make cross-domain ajax calls. If you're not familiar with the same origin policy you can start here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.

If this is not intended to be a cross-domain ajax call, try making your target url relative and see if the problem goes away. If you're really desperate look into the JSONP, but beware, mayhem lurks. There really isn't much more we can do to help you.

Solution 4 - Jquery

If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.

I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the Authorization header in my case ("x-li-format" and "X-UserName" here in your case.) I ended up passing it in a dummy format (e.g. AuthorizatinJack in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:

if (isset($_GET['AuthorizationJack'])) {
    $request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}

Solution 5 - Jquery

In my case I'm calling an API hosted by AWS (API Gateway). The error happened when I tried to call the API from a domain other than the API own domain. Since I'm the API owner I enabled CORS for the test environment, as described in the Amazon Documentation.

In production this error will not happen, since the request and the api will be in the same domain.

I hope it helps!

Solution 6 - Jquery

As answered by @Dark Falcon, I simply dealt with it.

In my case, I am using node.js server, and creating a session if it does not exist. Since the OPTIONS method does not have the session details in it, it ended up creating a new session for every POST method request.

So in my app routine to create-session-if-not-exist, I just added a check to see if method is OPTIONS, and if so, just skip session creating part:

    app.use(function(req, res, next) {
        if (req.method !== "OPTIONS") {
            if (req.session && req.session.id) {
                 // Session exists
                 next();
            }else{
                 // Create session
                 next();
          }
        } else {
           // If request method is OPTIONS, just skip this part and move to the next method.
           next(); 
        }
    }

Solution 7 - Jquery

"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Solution 8 - Jquery

Consider using axios

axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {

  if(res.data.error) {

  } else { 
    doAnything( res.data )
  }

}).catch(function (error) {
   doAnythingError(error)
});

I had this issue using fetch and axios worked perfectly.

Solution 9 - Jquery

I've encountered a very similar issue. I spent almost half a day to understand why everything works correctly in Firefox and fails in Chrome. In my case it was because of duplicated (or maybe mistyped) fields in my request header.

Solution 10 - Jquery

Use fetch instead of XHR,then the request will not be prelighted even it's cross-domained.

Solution 11 - Jquery

 $.ajax({
            url: '###',
            contentType: 'text/plain; charset=utf-8',
            async: false,
            xhrFields: {
                withCredentials: true,
                crossDomain: true,
                Authorization: "Bearer ...."
            },
			
            method: 'POST',

            data: JSON.stringify( request ),
            success: function (data) {
                console.log(data);
            }
        });

the contentType: 'text/plain; charset=utf-8', or just contentType: 'text/plain', works for me! regards!!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCorey OgburnView Question on Stackoverflow
Solution 1 - JqueryDark FalconView Answer on Stackoverflow
Solution 2 - JqueryDropoutView Answer on Stackoverflow
Solution 3 - JqueryjgitterView Answer on Stackoverflow
Solution 4 - JqueryAidinView Answer on Stackoverflow
Solution 5 - JquerygbonessoView Answer on Stackoverflow
Solution 6 - JqueryMaheshView Answer on Stackoverflow
Solution 7 - JqueryNoorullahView Answer on Stackoverflow
Solution 8 - JqueryEvhzView Answer on Stackoverflow
Solution 9 - JqueryAndrew TatomyrView Answer on Stackoverflow
Solution 10 - JqueryFei SunView Answer on Stackoverflow
Solution 11 - JqueryDavid LopesView Answer on Stackoverflow