IE9 jQuery AJAX with CORS returns "Access is denied"
Solution 1
This is a known bug with jQuery. The jQuery team has "no plans to support this in core and is better suited as a plugin." (See this comment). IE does not use the XMLHttpRequest, but an alternative object named XDomainRequest.
There is a plugin available to support this in jQuery, which can be found here: https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js
EDIT
The function $.ajaxTransport
registers a transporter factory. A transporter is used internally by $.ajax
to perform requests. Therefore, I assume you should be able to call $.ajax
as usual. Information on transporters and extending $.ajax
can be found here.
Also, a perhaps better version of this plugin can be found here.
Two other notes:
- The object XDomainRequest was introduced from IE8 and will not work in versions below.
- From IE10 CORS will be supported using a normal XMLHttpRequest.
Edit 2: http to https problem
Requests must be targeted to the same scheme as the hosting page
This restriction means that if your AJAX page is at http://example.com, then your target URL must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your target URL must also begin with HTTPS.
Solution 2
Building off the accepted answer by @dennisg, I accomplished this successfully using jQuery.XDomainRequest.js by MoonScript.
The following code worked correctly in Chrome, Firefox and IE10, but failed in IE9. I simply included the script and it now automagically works in IE9. (And probably 8, but I haven't tested it.)
var displayTweets = function () {
$.ajax({
cache: false,
type: 'GET',
crossDomain: true,
url: Site.config().apiRoot + '/Api/GetTwitterFeed',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (data) {
for (var tweet in data) {
displayTweet(data[tweet]);
}
}
});
};
Solution 3
Complete instructions on how to do this using the "jQuery-ajaxTransport-XDomainRequest" plugin can be found here: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest#instructions
This plugin is actively supported, and handles HTML, JSON and XML. The file is also hosted on CDNJS, so you can directly drop the script into your page with no additional setup: http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.1/jquery.xdomainrequest.min.js
Solution 4
The problem is that IE9 and below do not support CORS. XDomainRequest do only support GET/POST and the text/plain
conten-type as described here: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
So if you want to use all HTTP verbs and/or json etc you have to use another solution. I've written a proxy which will gracefully downgrade to proxying if IE9 or less is used. You do not have to change your code at all if you are using ASP.NET.
The solution is in two parts. The first one is a jquery script which hooks into the jQuery ajax processing. It will automatically call the webserver if an crossDomain request is made and the browser is IE:
$.ajaxPrefilter(function (options, originalOptions, jqXhr) {
if (!window.CorsProxyUrl) {
window.CorsProxyUrl = '/corsproxy/';
}
// only proxy those requests
// that are marked as crossDomain requests.
if (!options.crossDomain) {
return;
}
if (getIeVersion() && getIeVersion() < 10) {
var url = options.url;
options.beforeSend = function (request) {
request.setRequestHeader("X-CorsProxy-Url", url);
};
options.url = window.CorsProxyUrl;
options.crossDomain = false;
}
});
In your web server you have to receive the request, get the value from the X-CorsProxy-Url http header and do a HTTP request and finally return the result.
My blog post: http://blog.gauffin.org/2014/04/how-to-use-cors-requests-in-internet-explorer-9-and-below/
Solution 5
Building on the solution by MoonScript, you could try this instead:
https://github.com/intuit/xhr-xdr-adapter/blob/master/src/xhr-xdr-adapter.js
The benefit is that since it's a lower level solution, it will enable CORS (to the extent possible) on IE 8/9 with other frameworks, not just with jQuery. I've had success using it with AngularJS, as well as jQuery 1.x and 2.x.
Garrett
Updated on April 12, 2020Comments
-
Garrett about 4 years
The following works in all browsers except IE (I'm testing in IE 9).
jQuery.support.cors = true; ... $.ajax( url + "messages/postMessageReadByPersonEmail", { crossDomain: true, data: { messageId : messageId, personEmail : personEmail }, success: function() { alert('marked as read'); }, error: function(a,b,c) { alert('failed'); }, type: 'post' } );
I have another function which uses
dataType: 'jsonp'
, but I don't need any data returned on this AJAX call. My last resort will be to return some jibberish wrapped in JSONP just to make it work.Any ideas why IE is screwing up with a CORS request that returns no data?
-
Garrett about 12 yearsThanks! Any idea how to use that plugin?
-
dennisg about 12 yearsI am not entirely sure, but I've added my assumptions to my answer.
-
Kato almost 12 yearsThe "better version" of the plugin is innate; I just included it in my page and it automagically fixed my $.ajax calls :) Assuming, of course, that you have all the necessary headers in place.
-
user2918201 over 11 yearsI am missing something: neither of these are working for me. Include the script via a script tag, then just make ajax calls as normal?
-
user2918201 over 11 yearsIf I put an alert statement inside the function passed to ajaxTransport, that statement never gets executed. Additionally, the request (which is to 'localhost') doesn't show up in ie9's developer tool's network panel.
-
James Ford over 11 yearsThe jQuery.XDomainRequest.js plugin was exactly what I needed! I couldn't get the iexhr.js plugin to work for requests behind HTTP Basic Authentication, but XDomainRequest worked like a charm!
-
Volodymyr Otryshko over 11 yearsTo add to dennisg answer, xdr.js has a bug - ajaxTransport callback will not be called as is. I had to change it in accordance with stackoverflow.com/questions/12481560/… (added "+*" as a first argument of ajaxTransport call).
-
Nicholas Decker about 11 yearsThis worked for me. I didn't need Site.config().apiRoot + (which I'm assuming is for twitter....) But it works great, thanks for doing this.
-
JackMorrissey about 11 years@NicholasDecker Site.config().apiRoot was just implementation specific code to get the root URL of the API, nothing universal or fancy. Glad it helped!
-
Jack Marchetti about 11 yearsI was hoping this would work for me, but I'm trying to POST. wonder if that's the problem for me.
-
Randy L about 11 years@VolodymyrOtryshko -- Dude let me buy you a beer! Brilliant comment, fixed all my headaches.
-
mikermcneil almost 11 yearsJust a note to anyone with this problem-- in this case, if you have a <= IE7 requirement, and you don't have control over the server (e.g. can't make it support GET + script tags w/ JSONP) your best bet is a lightweight middleware server which translates the JSONP call to a POST and streams the response from the black box server back to the user.
-
Robusto almost 11 yearsThe $.ajaxTransport function you linked on github does absolutely nothing for me. And I really wanted it to. Darn.
-
Aaron almost 11 yearsjQuery.XDomainRequest.js makes sure that the current page and remote page are either both http or https. Does this mean that you cannot make a call to an https API from an http page?
-
Kushal Shah almost 11 yearsNote if you're dealing with an HTML response, the improved jQuery.XDomainRequest.js only deals with json and xml. My get now works by adding xdr.js. Wonderful (had done browser sniffing previously and done a XDocumentRequest which works for ie8 and ie10, but inexplicably, no go for ie9).
-
Clintm over 10 yearsIt's worth noting that the code that was linked to on moonscripts github repo is an old version that doesn't work. Be sure to get the latest version at: raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/…
-
Fernando Vezzali over 10 yearsHey @JackMarchetti, for POST requests it doesn't work for me.
-
zanona over 10 yearsthanks @SwampDiner, it works fine, it's a shame POST requests are sent as
text/plain
but it did the trick for me. -
Hari Honor about 10 years@Aaron I had problems with IE when I added the bitly API which was using
https
. Because the page itself washttp
, IE wouldn't allow it. -
Cymen about 10 yearsThis worked great -- drop in fix. Unbelievable that this issue exists in jQuery but... Thank you!
-
allicarn almost 10 years@Aaron, adding on to @HariKaramSingh's comment: changing protocols (
http
tohttps
), domains (google.com
tobing.com
), subdomains (mail.google.com
tomaps.google.com
), or protocols (google.com:80
- the default port togoogle.com:8080
) will all trigger a "cross domain" request. Basically everything before the first/
in your URL need to be identical. -
cracker almost 10 yearsI am having the same problem and i also refered the above links and put the jquery.xdomainrequest.min.js script in my current page but on post event it goes to jquery.min.js and result to No Access-Control-Allow-Origin header is present on the requested resource. what i need to do in this case?
-
JackMorrissey almost 10 years@cracker Are you only having issues with POST? Double check the script is loading after jQuery and your call matches MoonScript's documentation.
-
cracker almost 10 yearsit's going into jquery.min.js only but anyways thanks for the reply as i have added the Headers from back end and it's working fine now..
-
Hanna over 9 yearsThe extending ajax link is now dead.
-
Joshua Dance over 9 yearsThis worked perfect. Dropped the script in, our call
pd.$.get(pd.URL, function(data) { //do work with data }
works perfectly. Thanks. -
Frank over 9 yearsI've been trying to use this solution, but the cookies setted by the server are never being applied (the ASP.NET_SessionId in particular), so each calls is a new session. I'm on the same protocol, different domain (either different port or domain name), I've tried with jQuery 1.11 or 2.1. Did someone have something similar to this and resolved it, or is there no hope?
-
Frank over 9 yearsActually, it sets the cookies, but each time the server makes a cors request, the server returns a new set of cookies
-
Frank over 9 yearsI found my issue and patched the source. There really was something missing. I will fork and make a pull request later today with more details
-
John Washam almost 9 years@Frank, at least if you are using
XDomainRequest
, it does not allow cookies to be sent or received. See this MSDN blog post for more information, specifically the section titled "No authentication or cookies will be sent with the request." -
Stefan over 8 yearsIf I had read the coments, I would have saved myself a lot of time, but I wasted several hours trying to make ajax calls to an https service from an http site. I added it to the answer to avoid other people runnng into the sampe problem.
-
Stanislav over 8 yearsI had a problem with applying this solution because in my ajax call contained an option 'async: false', while in xdr.js there is an if condition that applies the fix only if async us true.