A Cors Post Request Works from Plain JavaScript, But Why Not with Jquery

A CORS POST request works from plain JavaScript, but why not with jQuery?

UPDATE: As TimK pointed out, this isn't needed with jquery 1.5.2 any more. But if you want to add custom headers or allow the use of credentials (username, password, or cookies, etc), read on.


I think I found the answer! (4 hours and a lot of cursing later)

//This does not work!!
Access-Control-Allow-Headers: *

You need to manually specify all the headers you will accept (at least that was the case for me in FF 4.0 & Chrome 10.0.648.204).

jQuery's $.ajax method sends the "x-requested-with" header for all cross domain requests (i think its only cross domain).

So the missing header needed to respond to the OPTIONS request is:

//no longer needed as of jquery 1.5.2
Access-Control-Allow-Headers: x-requested-with

If you are passing any non "simple" headers, you will need to include them in your list (i send one more):

//only need part of this for my custom header
Access-Control-Allow-Headers: x-requested-with, x-requested-by

So to put it all together, here is my PHP:

// * wont work in FF w/ Allow-Credentials
//if you dont need Allow-Credentials, * seems to work
header('Access-Control-Allow-Origin: http://www.example.com');
//if you need cookies or login etc
header('Access-Control-Allow-Credentials: true');
if ($this->getRequestMethod() == 'OPTIONS')
{
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Max-Age: 604800');
//if you need special headers
header('Access-Control-Allow-Headers: x-requested-with');
exit(0);
}

Why am I getting a CORS error with jQuery but not with XMLHttpRequest?

Problem(s)

The two requests are not equivalent

For the one sent via XHR, you're only setting the content type of the response:

xhr.open("GET", url, true);
// ...
xhr.responseType = 'application/json';

However, for the request sent via jQuery, you're setting the content type of the request itself to application/json:

.ajax({
// ...
method: 'GET',
contentType: 'application/json',
// ...
});

Use of the wildcard in conjunction with a credentialed request

A value of application/json for a request's content type makes it non-simple; as a result, a preflight request is triggered by your browser. However, you're responding to this preflight request with

Access-Control-Allow-Headers: *
Access-Control-Allow-Credentials: true

which is an incompatible combination. Therefore, CORS preflight fails, as explained in your browser's error message.

Invariably responding to preflight requests with a 403 status

Your latest edit shows that the status of the response to the preflight request is 403. However, for CORS preflight to be successful, the status must be in the 2xx range; see this other recent answer of mine about that.

Solution(s)

  1. Either don't specify the request's content-type to keep it simple, or (preferably) explicitly allow the Content-Type header in the Access-Control-Allow-Headers header rather than using the wildcard.
  2. Make sure you respond with a 2xx status to successful preflight requests. Be mindful that, because preflight requests never carry credentials, you should handle such requests in front of any authorisation middleware.

How to get a cross-origin resource sharing (CORS) post request working

I finally stumbled upon this link "A CORS POST request works from plain javascript, but why not with jQuery?" that notes that jQuery 1.5.1 adds the

 Access-Control-Request-Headers: x-requested-with

header to all CORS requests. jQuery 1.5.2 does not do this. Also, according to the same question, setting a server response header of

Access-Control-Allow-Headers: *

does not allow the response to continue. You need to ensure the response header specifically includes the required headers. ie:

Access-Control-Allow-Headers: x-requested-with 

AngularJS CORS http call not working but plain Ajax & jQuery working fine

CORS request called via Angular $http was triggering preflight (OPTIONS verb) but with plain Ajax call or jQuery Ajax its sent as non-preflighted CORS request as confirmed by debugger network tab in chrome.

As the service designed to handle the Simple CORS request call we need to ensure that Angular also prepare request in a way so that browser issue simple CORS request (See Simple vs Not so simple CORS request at MDN).

Solution: Remove the headers added by Angular by referring Access-Control-Request-Headers

GET request without any headers is treated as simple request

If you have configured Angular $http defaults, it will add these headers into request which makes it not so simple CORS as shown in below image.

All custom HTTP headers sent as Access-Control-Request-Headers when preflighted. Once server allows the communication as per CORS rule, browser sends the actual request(with original Method and Headers etc)

//remove custom headers by looking at Access-Control-Request-Headersvar headers = {  'Authorization': undefined,//undefined tells angular to not to add this header  'pragma': undefined,  'cache-control': undefined,  'if-modified-since': undefined};$http.get(url, {  headers: headers});

Failed to call CORS web service from jquery and plain javascript

You have two problems.

Leaving the page

You are triggering the Ajax request in response to a submit button being clicked.

Immediately after sending the request, the form submits and you leave the page, which causes the browser to abort the Ajax request.

The usual way to prevent the form from submitting when you are using an onclick attribute is to return false; from it. Now we are in the 21st century, however, I urge you to learn about addEventListener and move on from onclick.

Making a non-simple request

You are setting a bunch of custom request headers. These all require that the browser makes a pre-flight OPTIONS request to ask permission to make a cross-domain Ajax request with custom headers. The server doesn't grant permission for that. Don't set the custom request headers.

X-Requested-With is a non-standard (albeit common) hack to let a server send different content based on if the request is from Ajax or not (typically switching between JSON and an HTML document, something better suited to the Accept header). It isn't needed here. Don't set it.

Access-Control-Allow-etc are response headers. The server you are making the request to must respond with them to tell the browser that your site is allowed to use Ajax to access it. You can't set them on the client, it would be ridiculous for a site to grant itself permission to access a different site. Don't try to set these.

CORS working fine in jquery but not in angularjs

I was in the problem. by deep search i get ..
For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server. so if server does not allow it will throw errors. by default angular content type is application/json which is trying to send a OPTION request. but jquery default is
application/x-www-form-urlencoded; charset=UTF-8 so in your case for jquery is working and for angular it is not. try to overwrite angular default header . or allow it in server end. here is angular sample:

$http.post(url,data,{
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}

});

see http://api.jquery.com/jquery.ajax/ content-type for detail

CORS issue when trying to do JQuery post with json data, but not with plain text or x-www-form-urlencoded

The only values for the Content-Type header in a simple request are the following:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

Try to change the "application/json" to other content type or the browser will do a preflight request.

Refer to the CORS documentation: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

CORS error when jquery ajax request on api

There are 2 situations -

  1. If you have control over the api code then

    make changes in header and add your origin as well.

  2. If you don't have control to change CORS header that is coming from
    the api

    you have only one option create a backend code(your own api) in any language you prefer that make an http request and get the data. now use your own api to get data on your frontend.



Related Topics



Leave a reply



Submit