I have a JavaScript on a server named kopernikus.science
that wants to access a file on a different server named galileo.science
. Here a toy example of what I have in mind:
code residing on .js :
var request = new XMLHttpRequest();
request.open("GET","galileo.science/calendar", false);
request.send(null);
document.getElementById("calendar").innerHTML =
"<div>" + request.responseText.split('\n')[0] + "</div>";
Unfortunately, due to the "same origin policy" of modern web browsers, the script is forbidden from accessing the data on a different domain.
Of course, my question is:
How can I access the remote file anyway?
Solutions outside JavaScript are allowed, like mirroring the file in question or tweaking
.htaccess
. What are my options? Which require the least amount of permissions on the web server?
The file in question is a calendar in vcalendar format which changes regularly. I'm on a shared host and don't have sysadmin rights, but I can run PHP and CGI scripts and can change some parts of the .htaccess
file.
I have a JavaScript on a server named kopernikus.science
that wants to access a file on a different server named galileo.science
. Here a toy example of what I have in mind:
code residing on http://kopernikus.science/makecalendar.js :
var request = new XMLHttpRequest();
request.open("GET","galileo.science/calendar", false);
request.send(null);
document.getElementById("calendar").innerHTML =
"<div>" + request.responseText.split('\n')[0] + "</div>";
Unfortunately, due to the "same origin policy" of modern web browsers, the script is forbidden from accessing the data on a different domain.
Of course, my question is:
How can I access the remote file anyway?
Solutions outside JavaScript are allowed, like mirroring the file in question or tweaking
.htaccess
. What are my options? Which require the least amount of permissions on the web server?
The file in question is a calendar in vcalendar format which changes regularly. I'm on a shared host and don't have sysadmin rights, but I can run PHP and CGI scripts and can change some parts of the .htaccess
file.
-
1
If the domain names you show are the real ones, you should be able to use
document.domain
: developer.mozilla/en/document.domain – Pekka Commented Dec 16, 2010 at 11:55
5 Answers
Reset to default 8Some options:
- If you're in control of the servers and your users will be using an up-to-date web browser, you can use CORS. Sadly, there is no CORS support in IE7 or below. In IE8, it's there, but you have to use an
XDomainRequest
instead of anXMLHttpRequest
(other browsers, like Chrome and Firefox, handle CORS pletely transparently withXMLHttpRequest
). - If not, you can use JSONP, which works with all browsers.
- You can use
document.domain
to specify that both of those pages (if they're really subdomains of the samescience
domain) are in the same origin. That works well across browsers, but it has the disadvantage that you first have to load the target document into a window (probably a hidden iframe) before you can access it, because the target document also has to setdocument.domain
(to show that it wants to cooperate with you). - Another alternative, for public stuff, is using YQL as a proxy.
- If all of those fail, your only real option is to have a proxy script on your server that you query, which then uses server-side code to query the resource from the other domain (since this restriction only applies client-side).
Those are listed in roughly the order in which I would use them. E.g., use CORS if you control the servers and know your clients will be using up to date browsers; if not, look at JSONP (although from your ment below, you probably can't); if not either of those, perhaps document.domain
is the answer; etc., etc., working down the list to the option of last resort (proxying).
Unfortunately, due to the "same origin policy" of modern web browsers, the script is forbidden from accessing the data on a different domain.
But what you could do is use json-p.
Script and JSONP requests are not subject to the same origin policy restrictions.
<!DOCTYPE html>
<html>
<head>
<style>img{ height: 100px; float: left; }</style>
<script src="http://code.jquery./jquery-1.4.4.js"></script>
</head>
<body>
<div id="images">
</div>
<script>
$.getJSON("http://api.flickr./services/feeds/photos_public.gne?jsoncallback=?",
{
tags: "cat",
tagmode: "any",
format: "json"
},
function(data) {
$.each(data.items, function(i,item){
$("<img/>").attr("src", item.media.m).appendTo("#images");
if ( i == 3 ) return false;
});
});</script>
</body>
</html>
As a side note the modern browser support CORS(Internet Explorer 8+, Firefox 3.5+, Safari 4+, and Chrome).
Assuming you can deploy PHP on kopernikus.science, why not just proxy it there...
<?php
header('Content-Type: application/x-javascript');
print file_get_contents('http://galileo.science/calendar');
(and of course you could potentially cache it briefly on the proxy and client to cut down on network noise)
Update
If you want to cache....
<?php
header('Content-Type: application/x-javascript');
define("CACHEDIR", '/tmp/webcache/');
$cache_time=14 * 24 * 60 * 60; // cache for 2 weeks
$key=sha1('http://galileo.science/calendar');
if (@filemtime(CACHEDIR . $key) > time() - $cache_time) { // cache good
print file_get_contents(CACHEDIR . $key);
} else { // cache stale
$freshcopy=file_get_contents('http://galileo.science/calendar');
print $freshcopy;
if (!file_put_contents(CACHEDIR . $key, $freshcopy)) {
// report a problem writing files
}
}
Use JSONP. In the javascript, embed a new script element in the page that has the interface of the other server as source.
The server should return something like this:
callCallback({"some":"JSONString"});
This is a very known problem and JSONP is solution of the problem. You can google and fine a tons of information on that. You might consider this as example of usage JSONP with and without jQuery.
http://www.beletsky/2010/07/json-jsonp-and-same-origin-policy-issue.html