First off, this isn’t new. It’s not actually breaking any security protection, its just a way to perform cross-domain AJAX requests, something that is usually blocked by your browser.
Consider the following javascript code[1]:
var requestData = {
op: "fetchRecords",
id: 124,
key: "Q1GxWcxWOrKY"
};
var request = $.ajax({
url: "http://some-other-domain.com/json",
data: requestData,
dataType: 'json'
});
request.done(function(msg) {
callback(msg);
});
Unless the other domain is explicitly configured to allow for cross-domain AJAX requests, your request will fail.
Quick sidenote here: This failure may be very confusing, especially if you’re not aware of the same-origin policy restriction. The AJAX query will fail (so the fail and error methods will be called), but it will not indicate why it failed. More puzzling is that Firebug shows that the response header as 200 OK, but no data is passed back. Just a heads up in case this happens.
One option, if the server is setup to handle it, is JSONP. You can read more about it on the Wikipedia article, but unless the server is already configured to handle JSONP requests, or you can modify it to do so, this will not be an option for you.
When using third-party data providers, like in my case, these are not options.
What I needed was some way to asynchronously fetch the contents of a URL, but since I couldn’t do it directly, I did it indirectly.
To workaround this issue, I first created an extremely simple PHP script[2] that I called proxy.php:
<?php $file = file_get_contents($_GET['requrl']); echo $file; ?>
All this script does is fetch the URL that is specified in the requrl GET parameter and return its contents.
For example,
http://www.mysite.com/proxy.php?requrl=http://google.com
would just display the contents of google’s main page.[3]
And because this file, proxy.php, was hosted locally on the same domain, I’m able to send AJAX requests to it without issue.
If we take the javascript example above, it could be re-written to use the proxy as follows:
var requestData = {
op: "fetchRecords",
id: 124,
key: "Q1GxWcxWOrKY"
};
var request = $.ajax({
url: "proxy.php",
data: {requrl: "http://some-other-domain.com/json" + $.param(requestData) },
dataType: 'json'
});
request.done(function(msg) {
callback(msg);
});
Now, the client will fetch proxy.php via AJAX, the PHP server will fetch the specified URL and return it in response to the client’s AJAX query.
If you notice, we’re even able to pass GET parameters to the proxy and those parameters will be used by the webserver when fetching the page. This is because jQuery’s param function will URL encode the query string after creating it from the map, eliminating any ambiguity about where the query string parameters should be sent to.
The reason this doesn’t break the same-origin policy is because the same-origin policy is meant to prevent the client from making unintended/unexpected requests (and usually, exploiting the fact that the client’s cookies are sent and can be used to imitate a user’s intentional actions). In the case of this proposed workaround, it is the server that is making the request and your cookies will be safe.
With any code samples you find on the internet, this one included, you should read up on the functions you’re considering using before putting them in any (especially production) code.
Notes:
- This snippet, and the other javascript snippets require jQuery. Also, I specify the response dataType as json so that jQuery will parse the returned json and return an object. If you don’t want this, you can remove or edit this line.
- This is just a proof-of-concept proxy script and shouldn’t be used in practice. Without first checking things like referrer or requested URL against a whitelist, anyone could use the proxy for whatever they wanted. It’s just not a good idea to leave production code like this.
- Because google uses relative paths for things like CSS and images, the page you fetch via the proxy may look a bit different, specifically it may be missing styling, images or scripts. This is almost never an issue if you’re using a JSON API or even just scraping pages for the text data.








RSS Feed