http

Taking the Gloves Off XMLHttpRequest

Pow!Remember how the rapid enlightment around the potential of AJAX changed the web, and how swiftly it did so? It was 2004 / 2005, and though XMLHttpRequest had been viable for long before that, it took an advanced implementation of it by a few high profile web apps (notably, Gmail), combined with a meme-friendly naming, followed by swift support by the W3C and the major browsers to set web developers worldwide to work on rebuilding the web to deliver a decidedly more dynamic and desktop-software-like experience.

AJAX has always been hampered by an important restriction: due to the same-orgin policy implemented by the browsers (to prevent cross-site scripting attacks), XMLHttpRequest can only issue requests to resources on the same domain that it orginates from.

But oh what a world it would be if apps were empowered to make http requests to whichever domain they pleased. Recently, thanks to a new W3C standard and some ingenious hacks, the prospect of cross-orgin resource sharing (CORS) is becoming a reality.

Please Share

Please share... Rather than let the threat of XSS attacks prevent us all from enjoying the benefits of cross-site resource sharing, the wise owls at the W3C recently published a recomendation that would allow site publishers to opt-in to cross site requests. And the wise, oh let's say foxes, at the Mozilla foundation incorporated it whole-hog into Firefox 3.5. It's also in Safari 4, Chrome 2, and it may even see some traction in IE 8, though to no one's surprise Microsoft has their own idea about how to implement the standard.

That's not everybody. But someday soon, it may be close enough.

How it Works

CORS capability is established in the http headers. When the browser makes an http request, a compliant browser now includes an "Origin" header that tells the remote site where the request orginated from.

I'm going to use an example from the Mozilla docs to demonstrate. Here's the request in JS:

 

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/public-data/';
     
     function callOtherDomain(){
        if(invocation)
        {
            invocation.open('GET', url, true);
            invocation.onreadystatechange = handler;
            invocation.send();
        }

Let's look at the headers and see how a nice server should respond:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61 
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]

The first chunk before the linebreak is what Firefox sends the server. Notice the origin value. The header reponse from the server follows. And the magic is in the "Access-Control-Allow-Origin: *" bit. Access-Control-Allow-Origin is the server part of the handshake demanded by the new standard. The wildcard value here allows access from any domain, but it's easy to restrict to a whitelist of trusted domains.

This method will allow for GET or POST methods with content types of application/x-www-form-urlencoded, multipart/form-data, and text/plain. For other requests or more nuanced relationships to the server, the standard gets more complex. (See Pre-flighted requests and Requests with credentials.)

CORS for the Rest of Them

Portland local Jesse Hallett revently spoke to a Javascript user group about these recent developments in cross orgin resource sharing and to address the prospect of trying to pragmatically implement XHR now, he introduced flXHR, a client-side proxy implemented in Flash (from a vendor that's historically proven to be a little too adventurous about this CORS business for their own good).

flXHR works by redirecting Http requests through an invisible flash movie, which makes the cross site request under the more permissive aucpices of the flash environment, and then sends the response back to the Javascript client.

But if that sounds a little hairy, and if you only need to make GET requests, look into JSONp or CSSHttpRequest.

So, the gloves are off. Now what are you going to swing at?

 

Tagged as: http, javascript

Syndicate content