Cross origin resource sharing (CORS) allows resources from a web server to be accessed from a web page on another domain. The XMLHttpRequest level 2 specification added support for making cross domain requests but it should be noted that this specification is still a working draft. Traditionally I have always made cross domain requests from sites in a two stage process: 1) make a request to the server hosting the local domain for some data which then 2) makes the cross domain request, receives the response and returns this to the client. Now this process has merits, if you are hitting an external API chances are the service providers won’t be too impressed with you making a request for each user that visits your site and may even limit this. I wrote a nice little PHP class that can be used to avoid this by caching results locally but I’m going to pretend this isn’t an issue, just for today.
Making the request
For the cross origin request to work the remote origin needs to specify that it permits it’s resources to be accessed remotely with the Access-Control-Allow-Origin header. This header can either list the permitted domains or specify a wildcard (*) to allow all domains access to the specified resources. The browser must then set and send the ORIGIN header in the request to validate the domain making the request is permitted. To send cookies, HTTP authentication and client side SSL certificate information with the request you must switch the withCredentials flag to true on the XMLHttpRequest instance and the remote domain must have the Access-Control-Allow-Credentials header also set to true.
var xhr = new XMLHttpRequest; xhr.open("GET", "http://example.com", true); xhr.withCredentials = true; // send cookies, http auth etc xhr.send();
[Cross origin request example]
The cross origin request for what is indirectly termed in the spec as “not simple”—using methods like PUT and DELETE—are completed in two stages; A preflight request which basically makes checks with the remote origin that the request being made is valid and then the actual request if the preflight validates. The preflight request is made with the OPTIONS HTTP method and breaks down the credentials of the request in a set of Access-Control-Request-* headers such as:
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-Requested-With X-File-Name
Nicholas C. Zakas has written a more detailed post which I suggest you read and of course it’s always interesting to keep an eye on how the specification evolves. I have written and continue to develop a small Ajax library which supports CORS that you may also want to have a play with.