Fixing AJAX: XMLHttpRequest Considered Harmful
AJAX applications wouldn't be possible (or, at least, wouldn't be nearly as cool) without the
XMLHttpRequest object extensively to give users a responsive in-browser experience without the messiness of traditional HTML forms posting.
But the kind of AJAX examples that you don't see very often (are there any?) are ones that access third-party web services, such as those from Amazon, Yahoo, Google, and eBay. That's because all the newest web browsers impose a significant security restriction on the use of
XMLHttpRequest. That restriction is that you aren't allowed to make
XMLHttpRequests to any server except the server where your web page came from. So, if your AJAX application is in the page
http://www.yourserver.com/junk.html, then any
XMLHttpRequest that comes from that page can only make a request to a web service using the domain
www.yourserver.com. Too bad -- your application is on
www.yourserver.com, but their web service is on
webservices.amazon.com (for Amazon). The
XMLHttpRequest will either fail or pop up warnings, depending on the browser you're using.
On Microsoft's IE 5 and 6, such requests are possible provided your browser security settings are low enough (though most users will still see a security warning that they have to accept before the request will proceed). On Firefox, Netscape, Safari, and the latest versions of Opera, the requests are denied. On Firefox, Netscape, and other Mozilla browsers, you can get your
XMLHttpRequest to work by digitally signing your script, but the digital signature isn't compatible with IE, Safari, or other web browsers.
Solutions Worthy of Paranoia
There is hope, or rather, there are gruesome hacks, that can bring the splendor of seamless cross-browser
XMLHttpRequests to your developer palette. The three methods currently in vogue are:
- Application proxies. Write an application in your favorite programming language that sits on your server, responds to
XMLHttpRequests from users, makes the web service call, and sends the data back to users.
- Apache proxy. Adjust your Apache web server configuration so that
XMLHttpRequests can be invisibly re-routed from your server to the target web service domain.
- Script tag hack with application proxy (doesn't use
XMLHttpRequestat all). Use the HTML
The basic idea of all three hacks is the same: fool your user's web browser into thinking that the data is coming from the same domain as the web page.
A word of caution here: there is a good reason why
XMLHttpRequests are restricted. Allowing them to freely access any domain from within a web page opens up users to potential security exploitation. Not surprisingly, these three hacks, which offload the request to your web server, potentially threaten to disparage your web server's identity, if not its contents. Caution is advised before deploying them.
An application proxy is a program on your server that handles web service requests for AJAX client applications. You can write the proxy in your favorite programming language. A simple one is easy to write in PHP. This one is for Yahoo's REST web services called
proxy_curl.php. For security reasons, I've hardcoded the domain of the web service in the proxy. This proxy requires that your PHP implement have the
curl extension installed.
// Hardcode the hostname define('HOSTNAME', 'http://api.local.yahoo.com/'); // Get the REST call path from the AJAX application $path = $_GET['path']; // The URL to fetch is the hostname + path $url = HOSTNAME.$path; // Open the Curl session $session = curl_init($url); // Don't return HTTP headers. Do return the contents of the call curl_setopt($session, CURLOPT_HEADER, false); curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Make the call $xml = curl_exec($session); // The web service returns XML header("Content-Type: text/xml"); echo $xml; curl_close($session);
This is a minimal proxy implementation. Since the proxy is doing the actual web services requests, there's a lot of information about the user state and the success or failure of the request that could be returned to the AJAX application. A few things that you'd want to consider returning or managing are: handling secure (e.g. HTTPS) requests, returning any cookies, handling HTTP POSTs (this one only does GETs), returning the HTTP status code, and managing multiple requests (if your AJAX application makes multiple asynchronous requests, you'd want to identify which request you're receiving).
To call the proxy from your AJAX applications using
XMLHttpRequest, make the
XMLHttpRequest back to your own server and add the path to the web service as a variable to the web service call. Since I fetch
$_GET['path'] in the proxy above, it's expecting that you'll pass the parameter
// Call Yahoo's Geocode REST web service proxy_host = 'www.yourserver.com'; // Encode the parameter to the Geocode REST call address = encodeURI('1000 S Congress Avenue, Austin, TX'); // Include the path to the web service and double encode the path path = "MapsService/V1/geocode?appid=YahooDemo&location=" + address; proxy_request = encodeURIComponent(path); // The actual request proxy_request = "http://" + proxy_host + "/proxy_curl.php?path=" + proxy_request; .... .... // Make the request .....xmlhttprequest(proxy_request)....
Pages: 1, 2