Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

config.useXDomain to use XDomainRequest/CORS in IE #1047

Closed
wants to merge 4 commits into from

Conversation

ricardohbin
Copy link
Contributor

A new config param to use with $http. When true, IE uses XDomainRequest instead of XMLHttpRequest, useful to use CORS

@adamwynne
Copy link

will this work in $resource?

@ricardohbin
Copy link
Contributor Author

No. =/

The $resource calls $http with the same params: 'method', 'url' and 'data'.

I keep this behavior on it, so we cant pass the additional param 'useXDomain'

@syrusakbary
Copy link

You can use $http.defaults.useXDomain = true ;)
I really need this patch merged into Angular

@syrusakbary
Copy link

@mhevery merge this pull request as soon as possible please!!

@kvirkki
Copy link

kvirkki commented Aug 10, 2012

Is it so, @http.defaults.useXDomain = true will solve it for $resource?

@ricardohbin
Copy link
Contributor Author

@kvirkki in this pull request, it only works to $http. But i can implement it to $resource too, its very simple :)

@kvirkki
Copy link

kvirkki commented Aug 13, 2012

@ricardohbin that would be sweet! :)

@johnoscott
Copy link

if this is the solution to using $resource to access cross-site resources (such as a 3rd-party RESTful web service) then please pull it.

@ricardohbin
Copy link
Contributor Author

"$http.defaults.useXDomain = true" now works as expected, using $resource or $http =D

@johnoscott
Copy link

Hey Ricardo, do you have an example of this working ? A jsfiddle maybe ? I am keen to have $resource work cross-domain

@ricardohbin
Copy link
Contributor Author

@johnoscott sure! Check this: http://jsfiddle.net/ricardohbin/E3YEt/

@johnoscott
Copy link

@ricardohbin It doesnt seem to work for me (Chrome for Windows) when i use my http rest endpoint. See http://jsfiddle.net/johnoscott/JJE8b/3/

Hey would you mind discussing this on the angular group list ? I have started a discussion here :
https://groups.google.com/forum/?fromgroups=#!topic/angular/CSBMY6oXfqs

@ricardohbin
Copy link
Contributor Author

@johnoscott to CORS works, you need to set Access-Control-Allow-Origin header in response.

I dont detect it on yours.

http://www.w3.org/TR/cors/

@mhevery
Copy link
Contributor

mhevery commented Sep 4, 2012

Sorry for the delay, we are going thorough our PR backlog and we need CLA signed before we can accept this.

Thanks for your contribution! In order for us to be able to accept it, we ask you to sign our CLA (contributor's license agreement).

CLA is important for us to be able to avoid legal troubles down the road.

For individuals (a simple click-through form):
http://code.google.com/legal/individual-cla-v1.0.html

For corporations (print, sign and scan+email, fax or mail):
http://code.google.com/legal/corporate-cla-v1.0.html

@mhevery
Copy link
Contributor

mhevery commented Sep 4, 2012

Could we change this so that we don't have to use $http.defaults.useXDomain = true. The implementation should simply default to XDomainRequest on IE if CORS is needed. I am not sure what does the additional flag buy us.

@johnoscott
Copy link

I think the principled approach should be that Angular hides Internet Explorer 8 (and later)'s proprietary implementation of cross-domain requests (their XDomainRequest object) and just does the right thing when using $http and $resource.

I have just spent a few days properly understanding - and implementing CORS on my server. I originally thought that Angular didn't support CORS at all and this pull request was a fix for all browsers - I was mistaken. This is just a fix for IE (as the title clearly states) and Angular does indeed support CORS out of the box when the server is configured correctly.

I really don't want to have any browser checks in my Angular app to enable proprietary features. It should just work.

So my suggestion here is that for ie8, their XDomainRequest is just used by default for cross-site requests and their is no configuration required.

@ricardohbin
Copy link
Contributor Author

Hi @johnoscott and @mhevery, thanks for feedback!

I didnt make the XDomainRequest as default because it has some some restrictions compared to XHR.

Yes, CORS works on it, and this is fine.

But it only works with GET/POST, only text/plain is supported for the request's Content-Type header and few more limitations.

This link explain them very well: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx

If we force IE8/9 to always use XDomainRequest, many benefits of XHR will be lost (like consume RESTful resources).

Maybe a fallback to avoid this flag?

PS: already signed CLA. Thanks :)

@mhevery
Copy link
Contributor

mhevery commented Sep 12, 2012

Looked at the documentation and there seems to be no hope to make this work with CORS and most sites, and we don't want to maintain IE specific API. As much as we would like this, it is not going to happen. :-(

@tomagladiator
Copy link

I created a jsFiddle: http://jsfiddle.net/Xrdvm/1/
Doesn't works with Internet Explorer.
To see it in action : http://constraintsolver.com/lab/18_test/

@ricardohbin
Copy link
Contributor Author

Theres some reasons why it doesnt works:

  1. It doesn't use the angular version with useXDomain function (https://github.com/ricardohbin/angular.js/tree/useXDomain/preview)
  2. The jsFiddle is on HTTP and your resource calls HTTPS. Even with the patch, it needs the same protocol, this is a restriction of IE XDomainRequest object.

Maybe, if you fix these points, it will works on IE. Just remembering: the XDomainRequest doesnt works well with REST, how I said above :)

@ricardohbin
Copy link
Contributor Author

@tomagladiator the resource needs mine angular script too

@ricardohbin
Copy link
Contributor Author

@tomagladiator you fix the HTTP vs HTTPS that I mentioned?

@tomagladiator
Copy link

@ricardohbin
I don't know how to fix the HTTP vs HTTPS that you mentioned...
(Edit: deleted useless comments.)

@ricardohbin
Copy link
Contributor Author

@matohawk in this case, maybe a backend proxy is really the best approach. You request it, and it pass the request to the other-domain services :)

@matohawk
Copy link

matohawk commented Aug 7, 2013

@ricardohbin
Thanks
maybe both -
proxy for our own front-end (https://gist.github.com/jonsullivan/3126319)
jsonp for external user because it's hard to tell of your user API to create a proxy

@CMCDragonkai
Copy link

Ok, so basically it is impossible to issue CORS requests (cross browser) with Angular's $resource/$http, especially when it's from HTTP to HTTPS? I'm on 1.0.8 stable.

@ricardohbin
Copy link
Contributor Author

@CMCDragonkai in IE < 10, yes.

@CMCDragonkai
Copy link

Is there a quick work around, because I need it for IE9.

@ricardohbin
Copy link
Contributor Author

@CMCDragonkai I have a fork of this PR https://github.com/ricardohbin/angular.js/tree/useXDomain , but the angular version is a bit old.

@CMCDragonkai
Copy link

Can you point to the relevant areas or files? Or would it be better to just jury rig something with jquery?

@ricardohbin
Copy link
Contributor Author

@MrOrz
Copy link

MrOrz commented Sep 1, 2013

I uses cross domain request merely for fetching templates stored on the S3 bucket.

Inspired by the flXHR solution mentioned by @walski in #934 ,I replaced window.XMLHttpRequest with a thin interface that automatically switches between the original XMLHttpRequest and XDomainRequest based on the request URLs, so that my REST APIs (under the same origin as the page) still works with the original XMLHttpRequest.

Here is the patch I created as a drop-in replacement for XMLHttpRequest:
https://gist.github.com/MrOrz/6405400

It must be loaded before angular because inside angular it keeps a copy of XMLttpRequest. Hope it helps :)

@leefernandes
Copy link
Contributor

wtf, angular does not support CORS in IE 8 or 9?

wow

@jonymusky
Copy link

I am with v1.1.4 stable.
There is a patch to make CORS support in IE8 or IE9 ? its very important for me.

I know that its a CORS problem because when I change in Internet Explorer Options -> Security -> Custom Level -> Miscellaneous -> Access data sources across domains to ENABLED it works.

@ricardohbin
Copy link
Contributor Author

@jonymusky
Copy link

Thanks.
Now I get OPTIONS http://assets.local.com/js/locale/es.json Origin http://mysite.local.com is not allowed by Access-Control-Allow-Origin. angular1.2.0-rc2-mod.js:6515
XMLHttpRequest cannot load http://assets.local.com/js/locale/es.json. Origin http://mysite.local.com is not allowed by Access-Control-Allow-Origin.

But when I see the headers there are:
Access-Control-Allow-Headers:origin, x-requested-with, content-type
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*

But for any reason the request of the file is using OPTIONS method and not GET for example.

thanks.

@ricardohbin
Copy link
Contributor Author

Every CORS ajax do an OPTIONS "preflight" to check it destination headers. Probably this preflight has some error, and are failing your request.

You are sending ajax with X-Request-With?

@jonymusky
Copy link

Yes I send the X-Request-With with Ajax but the problem is in templateUrl that use a template from other domain and I am using an i18n module that use a json file from other domain.

@ProdigyView
Copy link

@ricardohbin I added one more try catch for IE to your patch.

try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e4) {}

And this patched solved the CORS problem I was having in FireFox. Why isn't this included yet?

@ProdigyView
Copy link

@ricardohbin With your patch and o version 1.08, all the IEs give the response 'Error'. No error message besides that, and the only thing in the console is a log message that happens at page load:

Log: Given Url cannot be accessed because it is not in the application's configuration.

Do you have any idea of a work around using your patch for this? Also, if I remove $httpProvider.defaults.useXDomain = true; it works in IE10, but will break when it's included.

@ProdigyView
Copy link

Made another small fix. IE10 does not need to use XDomainRequest, a conditional could be added to check for the version of IE. IE10 works again but IE8 and IE9 still throws the generic 'ERROR' from your 500 error code implementation..

var XHR = window.XMLHttpRequest || function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e4) {}
throw new Error("This browser does not support XMLHttpRequest.");
}, XDR = !window.msPerformance && isIE () != 10 && window.XDomainRequest || null;

function isIE () {
var myNav = navigator.userAgent.toLowerCase();
return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}

ksgy added a commit to ksgy/angular.js that referenced this pull request Nov 18, 2013
@pf-tara-maxwell
Copy link

This is a huge issue for an application we're developing right now. We really need to be able to do cross domain requests to our API subdomain. I really don't want to customize the angular code itself. Is there not a plugin or some other workaround? We tried using the xdomain.js approach, but that threw more Access Denied errors.

@walski
Copy link

walski commented Mar 5, 2014

@pf-tara-maxwell take a look at #934 folks have outlined several work arounds there.

@pf-tara-maxwell
Copy link

Yeah, I've looked at that thread quite a few times, now. And I tried the XDomain.js proxy solution, but it throws a different "Access Denied" within it's code.

@walski
Copy link

walski commented Mar 5, 2014

Quite frankly (as someone who solved that issue himself) I would strongly suggest for you to enable JSONP instead. If that is not an option I might be able to help with the flXHR solution. It requires Flash on old browsers, though 😱

@pf-tara-maxwell
Copy link

It would be great if we could use JSONP, but that is not an option with our current Restful API setup. We also can't really use the flXHR approach because it only works for Gets, and Posts. We have dropped support of IE7, but we still really need to support IE8 and especially IE9. 😢

@walski
Copy link

walski commented Mar 5, 2014

So what I did there for the POST only nature of flXHR is adding something like the Ruby on Rails magic _method field. Basically it was a middleware in our stack where you could pass in _method=PUT as a query param and it would treat that particular request as if it would have been a PUT/DELETE/whatever.

If all of that is not an option, you could try to setup a proxy under the same domain as the website which tunnels requests to your backend. Would one of these work?

@pf-tara-maxwell
Copy link

I'm trying the proxy approach, for now; but it will probably throw up some security concerns by our IT department. I think in the long term we're going to need to add some .Net MVC controllers in the same domain to make the API calls on the backend. Unfortunately, I'm getting a lot of slack over choosing to go with Angular for the majority of the application and just using .Net MVC for the authentication handling. It looks like we might should have used Angular with more of a MVVM pattern instead of MVC from the get go. But I didn't realize at the beginning of the project that we would be making cross-domain requests for all of the API calls and that it would be such an issue in IE 9 and below. It's possible that I can convince the product owners to drop support of IE8 in the near future, but probably not IE9.

@walski
Copy link

walski commented Mar 5, 2014

👍 Your position pretty much sounds like where we've been 9 month ago: Everything built around cross-domain XHR and then IE≤9 comes along ;) Hope you manage to get around this!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.