jquery $.get() is not using https - javascript

I have a page that is loaded over HTTPS, and within the page I do an XHR request to a relative file, using jQuery $.get(), and according to Chrome, this is trying to fetch the request via HTTP, so I get a cross origin access control error loading.
How do I force my request to use HTTPS?
If this isn't clear, I'm loading https://example.com/myapp/ and in turn there is this JS:
$.get('file', function(data) { ... }
All JS files, including jQuery, are loaded over https. Amazingly, I can't find anything in jQuery docs related to the protocol of XHR. This cannot possibly be an edge case, seems like a very typical thing to do (load a relative URL over http via AJAX). Am I missing something obvious?

It turns out this breaks:
$.get('directory', function(data) {...})
But this does not:
$.get('directory/', function(data) {...})
My sample code was misleading in using 'file' as the resource (I'd forgotten what I was fetching). So the first case is triggering a rewrite rule somewhere (the global Apache config which I don't have access to), and apparently that rewrite rule is not being smart about preserving the protocol. So the bug seems to lie with my hosting provider's Apache config, if it can be called a bug. To be clear, either one works in my app just fine if loaded over HTTP, so it is an actual bug that the rewrite breaks over HTTPS.
I doubt anyone will ever benefit from my question or answer, but if you're doing all of the above and have my same hosting provider, here it is!

Related

Externally load Json with jquery.getJSON

I don't know if this is a duplicate post or not, sorry if it is. I'm using jquery.getJSON to load a json on my server which works just fine. Although, if I try and load a json file on a different server it doesn't work. I know I don't have any code here (because there's not much point) but I just want to know if I'm using it wrong or if it isn't supposed to load external files. I'm using the iOS Safari browser if that effects anything.
EDIT: I've looked at the console (idk what the error thing really means, it's just red with an x by the url it's trying to get the json from) and it looks like it's not actually receiving the data. Plus, do remember I'm on iOS, not desktop so I couldn't look at the console in the "Develop tab :P
EDIT 2: Great! I think I got it working! http://skitty.xyz/getJSON/
You're most likely encountering a path issue; the purpose of $.getJSON is to acquire data via http GET request so yes, it is intended to work remotely. To diagnose your issue, make certain you can access the json file in your browser first: http://domain.com/my_data.json. If that works, use that as the URL you pass into $.getJSON:
$.getJSON( 'http://domain.com/my_data.json', function(data) {
// do something with your data
});
http://api.jquery.com/jquery.getjson/
jquery.getJSON uses ajax which is all about external resources. Here's a couple things to check for if it's not working on an external resource:
1: Is the path you specified correct? The usage is jquery.getJSON(path, callback). The path should be something you can just drop in your browser and see. If an incorrect path is your problem, you'll see a 404 in the console.
2: Is the resource http and your site https? Non-secure resources on secure pages will get blocked by browser security features. You'd see a error to this effect in the console.
3: Is CORS (Cross-origin resource sharing) enabled for your site on the external resource? Servers will sometimes use a whitelist of IPs and domains to determine what origins are allowed to make requests of it. You'd also see an error to this effect in the console.
There probably some other things to look for but this is where I'd start.
Also, by all means, use the debugging features of Safari to LQQK at the actual HTTP data-streams that are passing back-and-forth in response to what you're doing. (You might need to click on a preference to see the "Develop" menu, which will take you to "Show Web Inspector" and its Network tab.)
This approach will instantly answer many questions that a JavaScript-centered approach will not so-readily tell you. (And of course, you can look at the JavaScript console too ... and at the same time.) "The actual data streams, please." Safari will tell you "exactly what bytes" your app actually sent to the server, and "exactly what bytes" the server sent in return. "Priceless!™"
Are you saying you are using jquery ajax request to load some json data from a server?
check the "not working server" has the same end point as your server.
Check if the url you want to get data from is correct.
check if console logged any errors.
Also quote from http://api.jquery.com/jquery.getjson/
"Additional Notes:
Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, port, or protocol.
Script and JSONP requests are not subject to the same origin policy restrictions."

get xml data from url using js code [duplicate]

I'm developing a page that pulls images from Flickr and Panoramio via jQuery's AJAX support.
The Flickr side is working fine, but when I try to $.get(url, callback) from Panoramio, I see an error in Chrome's console:
XMLHttpRequest cannot load http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150. Origin null is not allowed by Access-Control-Allow-Origin.
If I query that URL from a browser directly it works fine. What is going on, and can I get around this? Am I composing my query incorrectly, or is this something that Panoramio does to hinder what I'm trying to do?
Google didn't turn up any useful matches on the error message.
EDIT
Here's some sample code that shows the problem:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';
$.get(url, function (jsonp) {
var processImages = function (data) {
alert('ok');
};
eval(jsonp);
});
});
You can run the example online.
EDIT 2
Thanks to Darin for his help with this. THE ABOVE CODE IS WRONG. Use this instead:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';
$.get(url, function (data) {
// can use 'data' in here...
});
});
For the record, as far as I can tell, you had two problems:
You weren't passing a "jsonp" type specifier to your $.get, so it was using an ordinary XMLHttpRequest. However, your browser supported CORS (Cross-Origin Resource Sharing) to allow cross-domain XMLHttpRequest if the server OKed it. That's where the Access-Control-Allow-Origin header came in.
I believe you mentioned you were running it from a file:// URL. There are two ways for CORS headers to signal that a cross-domain XHR is OK. One is to send Access-Control-Allow-Origin: * (which, if you were reaching Flickr via $.get, they must have been doing) while the other was to echo back the contents of the Origin header. However, file:// URLs produce a null Origin which can't be authorized via echo-back.
The first was solved in a roundabout way by Darin's suggestion to use $.getJSON. It does a little magic to change the request type from its default of "json" to "jsonp" if it sees the substring callback=? in the URL.
That solved the second by no longer trying to perform a CORS request from a file:// URL.
To clarify for other people, here are the simple troubleshooting instructions:
If you're trying to use JSONP, make sure one of the following is the case:
You're using $.get and set dataType to jsonp.
You're using $.getJSON and included callback=? in the URL.
If you're trying to do a cross-domain XMLHttpRequest via CORS...
Make sure you're testing via http://. Scripts running via file:// have limited support for CORS.
Make sure the browser actually supports CORS. (Opera and Internet Explorer are late to the party)
You need to maybe add a HEADER in your called script, here is what I had to do in PHP:
header('Access-Control-Allow-Origin: *');
More details in Cross domain AJAX ou services WEB (in French).
For a simple HTML project:
Python 2
cd project
python -m SimpleHTTPServer 8000
Python 3
cd project
python -m http.server 8000
Then browse your file.
Works for me on Google Chrome v5.0.375.127 (I get the alert):
$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
Also I would recommend you using the $.getJSON() method instead as the previous doesn't work on IE8 (at least on my machine):
$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
You may try it online from here.
UPDATE:
Now that you have shown your code I can see the problem with it. You are having both an anonymous function and inline function but both will be called processImages. That's how jQuery's JSONP support works. Notice how I am defining the callback=? so that you can use an anonymous function. You may read more about it in the documentation.
Another remark is that you shouldn't call eval. The parameter passed to your anonymous function will already be parsed into JSON by jQuery.
As long as the requested server supports the JSON data format, use the JSONP (JSON Padding) interface. It allows you to make external domain requests without proxy servers or fancy header stuff.
If you are doing local testing or calling the file from something like file:// then you need to disable browser security.
On MAC:
open -a Google\ Chrome --args --disable-web-security
It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.
We managed it via the http.conf file (edited and then restarted the HTTP service):
<Directory "/home/the directory_where_your_serverside_pages_is">
Header set Access-Control-Allow-Origin "*"
AllowOverride all
Order allow,deny
Allow from all
</Directory>
In the Header set Access-Control-Allow-Origin "*", you can put a precise URL.
In my case, same code worked fine on Firefox, but not on Google Chrome. Google Chrome's JavaScript console said:
XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234.
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"
I had to drop the www part of the Ajax URL for it to match correctly with the origin URL and it worked fine then.
As final note the Mozilla documentation explicitly says that
The above example would fail if the header was wildcarded as:
Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example,
the credential-cognizant content is returned to the invoking web
content.
As consequence is a not simply a bad practice to use '*'. Simply does not work :)
Not all servers support jsonp. It requires the server to set the callback function in it's results. I use this to get json responses from sites that return pure json but don't support jsonp:
function AjaxFeed(){
return $.ajax({
url: 'http://somesite.com/somejsonfile.php',
data: {something: true},
dataType: 'jsonp',
/* Very important */
contentType: 'application/json',
});
}
function GetData() {
AjaxFeed()
/* Everything worked okay. Hooray */
.done(function(data){
return data;
})
/* Okay jQuery is stupid manually fix things */
.fail(function(jqXHR) {
/* Build HTML and update */
var data = jQuery.parseJSON(jqXHR.responseText);
return data;
});
}
I use Apache server, so I've used mod_proxy module. Enable modules:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Then add:
ProxyPass /your-proxy-url/ http://service-url:serviceport/
Finally, pass proxy-url to your script.
For PHP - this Work for me on Chrome, safari and firefox
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null
header('Access-Control-Allow-Origin: null');
using axios call php live services with file://
I also got the same error in Chrome (I didn't test other browers). It was due to the fact that I was navigating on domain.com instead of www.domain.com. A bit strange, but I could solve the problem by adding the following lines to .htaccess. It redirects domain.com to www.domain.com and the problem was solved. I am a lazy web visitor so I almost never type the www but apparently in some cases it is required.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
Make sure you are using the latest version of JQuery. We were facing this error for JQuery 1.10.2 and the error got resolved after using JQuery 1.11.1
Folks,
I ran into a similar issue. But using Fiddler, I was able to get at the issue. The problem is that the client URL that is configured in the CORS implementation on the Web API side must not have a trailing forward-slash. After submitting your request via Google Chrome and inspect the TextView tab of the Headers section of Fiddler, the error message states something like this:
*"The specified policy origin your_client_url:/' is invalid. It cannot end with a forward slash."
This is real quirky because it worked without any issues on Internet Explorer, but gave me a headache when testing using Google Chrome.
I removed the forward-slash in the CORS code and recompiled the Web API, and now the API is accessible via Chrome and Internet Explorer without any issues. Please give this a shot.
Thanks,
Andy
There is a small problem in the solution posted by CodeGroover above , where if you change a file, you'll have to restart the server to actually use the updated file (at least, in my case).
So searching a bit, I found this one To use:
sudo npm -g install simple-http-server # to install
nserver # to use
And then it will serve at http://localhost:8000.

How to circumvent same-origin policy for a 3rd party https site?

I have a http:// site that needs to access a 3rd party JSON API that is exposed on an https:// site. I've read through Ways to circumvent the same-origin policy, but it seems the methods described there aren't appropriate for me:
The document.domain method - only works on subdomains.
The Cross-Origin Resource Sharing method - requires server cooperation.
The window.postMessage method - seems to require opening a popup window?
The Reverse Proxy method - A possible solution, but seems a bit too hard to setup.
http://anyorigin.com - seems to not support SSL.
Is this it? Must I implement solution 4, which seems rather complicated, or am I missing something?
Sorry, it seems that anyorigin.com does support https.
The reason I naively thought it doesn't, is because the API in question returns JSON, and I thought I would actually just get a plain text response (as in my tests with using anyorigin.com on google.com). When it returned just an object, I figured something was broken.
It appears the object simply returns the parsed JSON, so I'm good to go!
Update - anyorigin.com stopped working with some https sites a few weeks after I posted this, so I went ahead and wrote whateverorigin.org, an open source alternative to anyorigin.
You can use Ajax-cross-origin a jQuery plugin. With this plugin you use jQuery.ajax() cross domain.
It is very simple to use:
$.ajax({
crossOrigin: true,
url: url,
success: function(data) {
console.log(data);
}
});
You can read more here: http://www.ajax-cross-origin.com/
JSONP should be on your list, and higher up. Pretty much the standard. It requires server cooperation, but most any API should know what they're doing and support it.
here is a real basic writeup of how it works

“Origin null is not allowed by Access-Control-Allow-Origin” error for request made by application running from a file:// URL

I'm developing a page that pulls images from Flickr and Panoramio via jQuery's AJAX support.
The Flickr side is working fine, but when I try to $.get(url, callback) from Panoramio, I see an error in Chrome's console:
XMLHttpRequest cannot load http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150. Origin null is not allowed by Access-Control-Allow-Origin.
If I query that URL from a browser directly it works fine. What is going on, and can I get around this? Am I composing my query incorrectly, or is this something that Panoramio does to hinder what I'm trying to do?
Google didn't turn up any useful matches on the error message.
EDIT
Here's some sample code that shows the problem:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';
$.get(url, function (jsonp) {
var processImages = function (data) {
alert('ok');
};
eval(jsonp);
});
});
You can run the example online.
EDIT 2
Thanks to Darin for his help with this. THE ABOVE CODE IS WRONG. Use this instead:
$().ready(function () {
var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';
$.get(url, function (data) {
// can use 'data' in here...
});
});
For the record, as far as I can tell, you had two problems:
You weren't passing a "jsonp" type specifier to your $.get, so it was using an ordinary XMLHttpRequest. However, your browser supported CORS (Cross-Origin Resource Sharing) to allow cross-domain XMLHttpRequest if the server OKed it. That's where the Access-Control-Allow-Origin header came in.
I believe you mentioned you were running it from a file:// URL. There are two ways for CORS headers to signal that a cross-domain XHR is OK. One is to send Access-Control-Allow-Origin: * (which, if you were reaching Flickr via $.get, they must have been doing) while the other was to echo back the contents of the Origin header. However, file:// URLs produce a null Origin which can't be authorized via echo-back.
The first was solved in a roundabout way by Darin's suggestion to use $.getJSON. It does a little magic to change the request type from its default of "json" to "jsonp" if it sees the substring callback=? in the URL.
That solved the second by no longer trying to perform a CORS request from a file:// URL.
To clarify for other people, here are the simple troubleshooting instructions:
If you're trying to use JSONP, make sure one of the following is the case:
You're using $.get and set dataType to jsonp.
You're using $.getJSON and included callback=? in the URL.
If you're trying to do a cross-domain XMLHttpRequest via CORS...
Make sure you're testing via http://. Scripts running via file:// have limited support for CORS.
Make sure the browser actually supports CORS. (Opera and Internet Explorer are late to the party)
You need to maybe add a HEADER in your called script, here is what I had to do in PHP:
header('Access-Control-Allow-Origin: *');
More details in Cross domain AJAX ou services WEB (in French).
For a simple HTML project:
Python 2
cd project
python -m SimpleHTTPServer 8000
Python 3
cd project
python -m http.server 8000
Then browse your file.
Works for me on Google Chrome v5.0.375.127 (I get the alert):
$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
Also I would recommend you using the $.getJSON() method instead as the previous doesn't work on IE8 (at least on my machine):
$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
alert(json.photos[1].photoUrl);
});
You may try it online from here.
UPDATE:
Now that you have shown your code I can see the problem with it. You are having both an anonymous function and inline function but both will be called processImages. That's how jQuery's JSONP support works. Notice how I am defining the callback=? so that you can use an anonymous function. You may read more about it in the documentation.
Another remark is that you shouldn't call eval. The parameter passed to your anonymous function will already be parsed into JSON by jQuery.
As long as the requested server supports the JSON data format, use the JSONP (JSON Padding) interface. It allows you to make external domain requests without proxy servers or fancy header stuff.
If you are doing local testing or calling the file from something like file:// then you need to disable browser security.
On MAC:
open -a Google\ Chrome --args --disable-web-security
It's the same origin policy, you have to use a JSON-P interface or a proxy running on the same host.
We managed it via the http.conf file (edited and then restarted the HTTP service):
<Directory "/home/the directory_where_your_serverside_pages_is">
Header set Access-Control-Allow-Origin "*"
AllowOverride all
Order allow,deny
Allow from all
</Directory>
In the Header set Access-Control-Allow-Origin "*", you can put a precise URL.
In my case, same code worked fine on Firefox, but not on Google Chrome. Google Chrome's JavaScript console said:
XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234.
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"
I had to drop the www part of the Ajax URL for it to match correctly with the origin URL and it worked fine then.
As final note the Mozilla documentation explicitly says that
The above example would fail if the header was wildcarded as:
Access-Control-Allow-Origin: *. Since the Access-Control-Allow-Origin explicitly mentions http://foo.example,
the credential-cognizant content is returned to the invoking web
content.
As consequence is a not simply a bad practice to use '*'. Simply does not work :)
Not all servers support jsonp. It requires the server to set the callback function in it's results. I use this to get json responses from sites that return pure json but don't support jsonp:
function AjaxFeed(){
return $.ajax({
url: 'http://somesite.com/somejsonfile.php',
data: {something: true},
dataType: 'jsonp',
/* Very important */
contentType: 'application/json',
});
}
function GetData() {
AjaxFeed()
/* Everything worked okay. Hooray */
.done(function(data){
return data;
})
/* Okay jQuery is stupid manually fix things */
.fail(function(jqXHR) {
/* Build HTML and update */
var data = jQuery.parseJSON(jqXHR.responseText);
return data;
});
}
I use Apache server, so I've used mod_proxy module. Enable modules:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Then add:
ProxyPass /your-proxy-url/ http://service-url:serviceport/
Finally, pass proxy-url to your script.
For PHP - this Work for me on Chrome, safari and firefox
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null
header('Access-Control-Allow-Origin: null');
using axios call php live services with file://
I also got the same error in Chrome (I didn't test other browers). It was due to the fact that I was navigating on domain.com instead of www.domain.com. A bit strange, but I could solve the problem by adding the following lines to .htaccess. It redirects domain.com to www.domain.com and the problem was solved. I am a lazy web visitor so I almost never type the www but apparently in some cases it is required.
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
Make sure you are using the latest version of JQuery. We were facing this error for JQuery 1.10.2 and the error got resolved after using JQuery 1.11.1
Folks,
I ran into a similar issue. But using Fiddler, I was able to get at the issue. The problem is that the client URL that is configured in the CORS implementation on the Web API side must not have a trailing forward-slash. After submitting your request via Google Chrome and inspect the TextView tab of the Headers section of Fiddler, the error message states something like this:
*"The specified policy origin your_client_url:/' is invalid. It cannot end with a forward slash."
This is real quirky because it worked without any issues on Internet Explorer, but gave me a headache when testing using Google Chrome.
I removed the forward-slash in the CORS code and recompiled the Web API, and now the API is accessible via Chrome and Internet Explorer without any issues. Please give this a shot.
Thanks,
Andy
There is a small problem in the solution posted by CodeGroover above , where if you change a file, you'll have to restart the server to actually use the updated file (at least, in my case).
So searching a bit, I found this one To use:
sudo npm -g install simple-http-server # to install
nserver # to use
And then it will serve at http://localhost:8000.

JSONP callback doesn't execute when running at localhost

This is bizarre, I was wondering if anyone could shed some light on why this happened.
Basically, I've been pulling my hair out trying to test JSONP out so I can implement a JSON web service that other sites can use. I'm doing development on localhost--specifically, Visual Studio 2008 and Visual Studio 2008's built-in web server.
So as a JSONP test run w/ jQuery, I implemented the following:
$().ready(function() {
debugger;
try {
$.getJSON("<%= new Uri(Request.Url, "/").ToString() %>XssTest?callback=?", function(data) {
alert(data.abc);
});
} catch (err) {
alert(err);
}
});
And on the server ..
<%= Request["callback"] %>({abc : 'def'})
So what ends up happening is I set a breakpoint on the server and I get the breakpoint both on the first "debugger;" statment in the client-side script as well as on the server. The JSONP URL is indeed being invoked after the page loads. That's working great.
The problem I was having was that the callback would never execute. I tested this in both IE8 as well as Firefox 3.5. Neither one would invoke the callback. The catch(err) was never reached, either. Nothing happened at all!
I'd been stuck on this for a week, and even tested with a manually keyed HTTP request in Telnet on the specified port to be sure that the server is returning the format...
callbackfn({abc : 'def'})
.. and it is.
Then it dawned on me, what if I change the hostname from localhost to localhost with a globalizer ('.'), i.e http://localhost.:41559/ instead of http://localhost:41559/ (yes, adding a dot to any hostname is legal, it is to DNS what global:: is to C# namespaces). And then it worked! Internet Explorer and Firefox 3.5 finally showed me an alert message when I just added a dot.
So this makes me wonder, what is going on here? Why would late script tag generation work with an Internet hostname and not with plain localhost? Or is that the right question?
Clearly this is implemented for security reasons, but what are they trying to secure?? And, by getting it to work with a dot, did I just expose a security hole in this security feature?
By the way, my hosts file, while altered for other hosts, has nothing special going on with localhost; the default 127.0.0.1 / ::1 are still in place with no overrides below.
FOLLOW-UP: I got past this for local development purposes by adding:
127.0.0.1 local.mysite.com
.. to my hosts file, then adding the following code to my global.asax:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (Request.Headers["Host"].Split(':')[0] == "localhost")
{
Response.Redirect(
Request.Url.Scheme
+ "://"
+ "local.mysite.com"
+ ":" + Request.Url.Port.ToString()
+ Request.Url.PathAndQuery
, true);
}
}
I'm going to throw an answer out there; after some thought I've reached my own conclusions.
It could be that this is a security feature that's implemented to try to thwart an Internet web site from invoking JSONP services running on the client machine.
A web site could just go through a list of ports and keep invoking localhost on different ports and paths. 'Localhost' is one of few DNS hostnames that are dynamic in meaning depending on when and where it's queried, making the potential targets vulnerable. And yes, the fact that appending a dot (.) to 'localhost' ('localhost.') produces a working workaround does expose a security vulnerability, but does offer a [tentative] workaround for development puposes.
A better approach is to map the loopback IP to a new hostname entry in the hosts file so that it works locally, isn't prone to be "fixed" by a browser update, and doesn't work anywhere else but on the development workstation.
I'm experiencing a similar problem. Most of the solutions I've tried work with IE (7), but I'm having difficulty getting Firefox (3.5.2) to play ball.
I've installed HttpFox in order to see how my server's responses are being interpreted on the client, and I'm getting NS_ERROR_DOM_BAD_URI. My situation is a little different to yours though, as I'm trying to invoke a JSONP call back to the same site the hosting page came from, and then this call is responding with a 302 redirect to another site. (I'm using the redirect as a convenient way to get cookies from both domains returned to the browser.)
I'm using jQuery, and I originally tried doing a standard AJAX call via $.ajax(). I figured that as the initial request was to the same site as the hosting page, Firefox would just follow the 302 response to another domain. But no, it appeared to fall foul of XSS defenses. (Note that contrary to what Returning redirect as response to XHR request implies, jQuery does follow the 302 redirect for a standard dataType="json" call: a redirect to the same domain works fine; a redirect to another domain generates NS_ERROR_DOM_BAD_URI in the browser.) As an aside, I don't see why same-domain 302 redirects to other domains can't just be followed - after all, it's the hosting page's domain that is issuing the redirect, so why can't it be trusted? If you're worried about scripting injection attacks, then the JSONP route is open for abuse anyway...
jQuery's $.getJSON() with a ?callback=? suffix also fails in Firefox with the same error. As does using $.getScript() to roll my own JSONP <script> tag.
What does appear to work, is having a pre-existing <script id="jsonp" type="text/javascript"></script> in the HTML and then using $("jsonp").attr("src", url + "?callback=myCallback") to invoke the JSONP call. If I do that, then the cross-domain 302 redirect is followed and I get my JSON response passed to myCallback (which I've defined at the same time as the <script/> tag).
And, yes, I'm developing all this using Cassini with localhost:port URLs. Cassini won't respond to non-localhost URLs, so I can't easily try local.mysite.com to see if that has any affect on the solutions I've tried above. However, sticking a dot at the end of localhost appears to have fixed all my problems!
Now I can go back to a standard $.ajax({ ... dataType:"jsonp" ... }) call with localhost__.__:port instead of localhost:port and all is well. I find it interesting that modifying the src attribute of a script tag that pre-exists in the page's HTML does allow ordinary localhost URLs to be invoked - I guess following your thought process, this could be another security vulnerability.

Categories