Can XDomainRequest be made to work with SSL? - ajax

I have code that uses Microsoft's XDomainRequest object in IE8. The code looks like this:
var url = "http://<host>/api/acquire?<query string>";
var xdr = new XDomainRequest();
xdr.onload = function(){
$.("#identifier").text(xdr.responseText);
};
xdr.open("GET", url);
xdr.send();
When the scheme in "url" is "http://" the command works fine. However, when the scheme is "https://" IE8 gives me an "Access denied" JavaScript error. Both schemes work fine in FF 3.6.3, where I am, of course, using XmlHttpRequest. With both browsers I am complying with W3C Access Control. "http://" works cross origin for both browsers. So the problem is with IE8, XDomainRequest, and SSL.
The SSL certificate is not the problem. If I type https://<host>/ into the address bar of IE8, where <host> is the same as in "url" above, the page loads fine.
So we have the following:
- hitting https://<host>/ directly from the browser works fine;
- hitting https://<host>/api/acquire?<query string> via XDomainRequest is not allowed.
Can it be done? Am I leaving something out?

Apparently, the answer is here: Link
Point 7 on this page says, "Requests must be targeted to the same scheme as the hosting page."
Here is some of the supporting text for point 7:
"It was definitely our intent to prevent HTTPS pages from making
XDomainRequests for HTTP-based resources, as that scenario presents a
Mixed Content Security Threat which many developers and most users do
not understand.
However, this restriction is overly broad, because it prevents HTTP
pages from issuing XDomainRequests targeted to HTTPS pages. While it’s
true that the HTTP page itself may have been compromised, there’s no
reason that it should be forbidden from receiving public resources
securely."
It would appear at present that the answer to my original question is: YES, if the hosting page can use the "https://" scheme; NO, if it cannot.

Related

WebAPI SignalR Negotiate response different on different browsers

The main problem about Access-Control-Allow-Origin I think. But when I configure the Web API project as defined in the given documentation, it still not working in chrome and firefox but working in IE well (it is about IE thinks localhost is not cross domain, AFAIK). I tried different ways to make it work but no result.
I put the example project to github repository. Project is very simple. There are two applications working on cross domains. It is very simple chat application like in signalr examples.
You must change the value of api host in client javascript file:
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApp/Scripts/app/chat.js#L2
When you open the Chat page in mvc project, there will be two requests to api application
1- Regular ajax request (which is working fine)
2- Signalr negotiate request (cancelled)
And also I don't think browser disables the CORS because of if it disables there would not be an hit to server. So I think it is about browser but not about browser disables (something else).
Details are in repository
Readme: https://github.com/yusufuzun/WebApiSignalR/blob/master/README.md
Fiddler Results: https://github.com/yusufuzun/WebApiSignalR/blob/master/FiddlerResults
The bad part about it also is server returning 500 with this error:
System.InvalidOperationException: 'chat' Hub could not be resolved.
Which hub name is chat also.
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Hubs/ChatHub.cs#L10
You can enable CORS for Web Api in project with different ways for test purposes. Each one is giving different errors all about XMLHttpRequest Access-Control-Allow-Origin.
I commented them, so you can uncomment and make test for each one:
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Global.asax.cs#L24
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/App_Start/WebApiConfig.cs#L14
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/App_Start/WebApiConfig.cs#L16
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Controllers/ChatController.cs#L17
So what is going on here?
After I talked with David Fowler in JabbR, he mentioned the thing about using CORS with SignalR. My signalr startup code was wrong. So after changing the startup code like in his advice it worked well.
He also mentioned SignalR and Web API are working with different CORS definitions. So enabling or disabling one doesn't affect other.
Here is the new startup code:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(new HubConfiguration()
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
});
The old one:
app.MapSignalR(new HubConfiguration()
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
}).UseCors(CorsOptions.AllowAll);
Hope it helps to somebody out there.

Angular JS $http request does not reach the server in ie8

I'm having issues with using $http on ie8. The request does not reach the server, until I hit a refresh. Coming back to the same link still has the same problem until I hit refresh again.
The weird thing is if the web server is on LAN and the request is made to a server in LAN, it works fine. But if the webserver is hosted remotely, it does not work!
Here is the code:
Index.html
{{test}}
Controller
app.controller(
"TestController",
function( $scope, $http) {
var url = '/test/get_data';
$http.get(url).success(function(data) {
$scope.test = data;
});
}
);
I got this error: TypeError: Object doesn't support this property or methodundefined
I prepared a JSFiddle earlier but JSFiddle is broken in ie8 so I don't provide it here.
Unfortunately I don't have a remote server that I can share with you.
Edit
Previously I used an external url which gave me 'Access Denied' error in ie because of Same Origin Policy as mentioned by one answer below. But this was not my original problem. I still have the issue above when request is from the same origin
This is a cross domain request, which is not allowed in ajax because of Same Origin Policy.
There are two solutions for this
1. JSONP: It is a cross browser way to handle cross domain ajax requests using javascript callback mechanism
2. CORS: It is a HTML5 standard, it is implemented by most of the modern browsers except IE
Mongodb lab is not supporting jsonp since it has support for CORS, that is why your request is failing in IE and works in Chrome and other browsers.
As per this post they do not have any plan to support jsonp, so I don't thick there is a way to make this work in IE.
So I found the fix... Hope this helps anyone out there that experience this problem
Angular script needs to be loaded after jQuery. I didn't have this because Yii framework that I use autoloads jQuery and the angular was not included after the jQuery.
All the controller functions need to be at the end of body section (just before the closing )
Updating to angular 1.0.5 seems to fix the problem. The problem occurred in 1.0.4 with all the above tricks. I think is related to fix 791804bd

Ajax call getting canceled by browser

I am using the Prototype JS framework to do Ajax calls. Here is my code:
new Ajax.Request( '/myurl.php', {method: 'post', postBody: 'id='+id+'&v='+foo, onSuccess: success, onFailure: failed} );
function success(ret) {
console.log("success",ret.readyState, ret.status);
}
function failed(ret) {
console.log("failed",ret.readyState, ret.status);
}
Most of the time, this works fine and the success function is called with a status code of 200. About 5% of the time on Safari the success function is called with a status code of 0. In this case, when I look in the Network tab of the web inspector, the ajax call is listed with a status of "canceled". I can confirm with server logs, that the request never hit the server. It's as if the ajax request was immediately canceled without even trying to connect to the server. I have not found any reliable way to reproduce this, it seems to be random. I do it 20 times and it happens once.
Does anyone know what would cause the ajax call to get canceled or return a status code of 0?
The cause may be the combination of http server and browser you are using. It doesn't seems like an error of the PrototypeJS library.
Multiple sources states that keep-alive parameter of the HTTP connection seems to be broken in Safari (see here, here or here). On Apache, they recommend adding this to the configuration:
BrowserMatch "Safari" nokeepalive
(Please check the appropriate syntax in your server documentation).
If Safari handles badly HTTP persistent connections with your server, it may explain what you experiences.
If it's not too complex for you, I would try another HTTP server, there are plenty available on every OS.
We lack a bit of information to answer fully your answer, though. The server issue is a lead but there may be others. It would be nice to know if it does the same thing in other browsers (Firefox with Firebug will display this kind of information, Chrome, Opera and IE have development builtin toolboxes). Another valid question would be how often you execute this AJAX request per second (if relevant).
I know this is an old topic, but I wanted to share a solution for Safari that might save others some time. The following line really solved all problems:
BrowserMatch "^(?=.*Safari)(?=.*Macintosh)(?!.*Chrom).*" nokeepalive gzip-only-text/html
The regex makes sure only Safari on Mac is detected, and not Mobile Safari and Chrome(ium) and such. Safari for Windows is also not matched, but the keepalive problem seems to be a Mac-Safari combination only. In addition, some Safari versions do not handle gzipped css/js well.
All our symptoms of our site crashing or CSS not completley loading in different versions of Safari which caused me to nearly pull my hair out (Safari really is the new IE) have been solved for us with this Apache 'configuration hack'.

Why does this cross-domain request work in other browsers but not IE9?

I have some Ajax code that is working in Safari, Chrome and Firefox but not in IE9.
The page is on http://foo.com/test.aspx and it's making an AJAX request to a webservice hosted on https://service.foo.com. I thought I wouldn't have any cross-domain issues but given IE9 is blocking it, it appears that I do :(
var tempUrl = "https://service.foo.com/dummy.svc/test?hi=bye";
$.get(tempUrl, "html");
As I mentioned, the code works in the other 3 browsers, just not IE9. (I'm only concerned about IE9, not IE8 or older).
I did some digging and found this article on MSDN that says:
Cross-domain requests require mutual
consent between the Web page and the
server. You can initiate a
cross-domain request in your Web page
by creating an XDomainRequest object
off the window object and opening a
connection to a particular domain. The
browser will request data from the
domain's server by sending an Origin
header with the value of the origin.
It will only complete the connection
if the server responds with an
Access-Control-Allow-Origin header of
either * or the exact URL of the
requesting page. This behavior is part
of the World Wide Web Consortium
(W3C)'s Web Application Working
Group's draft framework on client-side
cross-domain communication that the
XDomainRequest object integrates with.
Before I go down the path of using XDR I wanted to verify with people smarter than me whether this is the right approach or not.
Add Response.AddHeader("Access-Control-Allow-Origin", "*"); to my page
Create condition jscript code that detects IE9 and uses XDR instead of the regular jquery call I'm using with $.get.
Am I totally off or is this the right way to go about this?
(Assuming it's the right way to go, where does the Acecss-Control-Allow-Origin response header go -- on my page at http://foo.com/test.aspx or on the webservice at https://service.foo.com?)
Instead of $.ajax(), use this custom code:
function newpostReq(url,callBack)
{
var xmlhttp;
if (window.XDomainRequest)
{
xmlhttp=new XDomainRequest();
xmlhttp.onload = function(){callBack(xmlhttp.responseText)};
}
else if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest();
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
callBack(xmlhttp.responseText);
}
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
Note: this works for GET requests.
To adapt it on POST requests change the following lines:
function newpostReq(url,callBack,data)
data is the URL encoded parameters of the post requests such as : key1=value1&key2=value%20two
xmlhttp.open("POST",url,true);
try{xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");}catch(e){}
xmlhttp.send(data);
To summarize, open the connection as POST request (Line 1), set the request header for urlencoded type of the post data (wrap it with try-catch for exceptional browsers) (Line 2), then send the data (Line 3).
i just wrestled with the same problem.
php backend, right mime and yes,
header('Access-Control-Allow-Origin: *');
worked in almost* every browser - except IE9.
seems like jQuery.getJSON doesn't automatically do XDR for ie9 - after creating a service proxy on the same domain, it worked.
* almost - opera acts up too.
edit: okay, opera did have the same problem as ie9. works like a charm now.
note: chrome, safari and the firefoxes (3.6-5) had no problem with the cross domain requests with ACAO:*.
what i don't understand is why a) microsoft uses a different object for cross domain requests and b) why jquery doesn't switch transparently (or at least provide an option to choose).
If this works in the other browsers (which support CORS), then your SVC seems to already be supporting this, but to be sure, use Fiddler2 to see what is going on.
The Access-Control-Allow-Origin header is used on the resource being requested, not on the page requesting it.

HTTP Referrer and IE7 and IE8

Hi i've tried the following to find the referrer in MSIE / IE7 and IE8 but its returning blank each time;
PHP:
<?
echo $_SERVER['HTTP_REFERER'];
?>
JAVASCRIPT:
document.write('Thanks for visiting from ' + document.referrer);
Does any know what the issue could be I'm referering using document.location from a page on another domain and work fine with all other browsers minus MSIE.
Any help would be great!
The HTTP Referer header is not required by the HTTP Protocol :
It is only sent as an information
The browser can, or cannot, send it (Which would explain why you're getting it with some browsers, and not getting it with some others)
Some firewall / security software could remove it, I suppose, in some situations (I've seen that, some years ago, if I remember correctly)
It can be forged easily by the user
Which means that you cannot rely on the Referer for your application : you can use it to provide some additionnal functionnality, but your application must work even if it's not there, or not correct.
HTTP_REFERRER does't work in IE browser it works fine for all browsers like mozilla, safari, opera etc... Referrer method doesn't recognize in IE it will return null when we apply it for IE. Actually using HTTP_REFERRER itself is not a right criteria because we can't expect it will work or not as it is not a standard HTTP HEADER.
Here's a hack you might try:
var referLink = document.createElement('');
document.body.appendChild(referLink);
referLink.click();

Resources