Enabling Cross Domain Ajax Requests using CORS
Okay, I usually harped about the one main limitation of Ajax Requests – Same Origin Policy. This policy exists to restrict XSS (Cross Site Scripting) attacks and vulnerabilities. But that is also a big party pooper when you want to legally make an Ajax call from your site to another domain, directly from the browser in order to load content from the other domain. There are exceptions to this policy that allow for embedding of certain resources like images, scripts, stylesheets, media and some other types of content. Thus CDNs for loading scripts like jQuery and stylesheets from Bootstrap are quite common and actually recommended too. But that’s not Ajax. Ajax begins when an XMLHttpRequest object is created. And that object cannot normally be used to make a request to any other domain other than the one it is currently on.
For example, if a script on a page on the domain http://DomainA.com wants make an Ajax request, it is limited to make the request to any resource only on the http://DomainA.com domain by the Same Origin Policy. If the script tries to make a request to http://DomainB.com, it will be actively blocked by the browser. The policy applies to Port numbers, sub-domains and protocols too. This is a good thing to protect users from visiting untrusted sites and having those sites steal the users sessions from trusted websites. But to legally make a script load content from another domain, say like your recent tweets, your facebook posts or your flickr feed or weather data or stock info from an online API or Web Service, this policy restricts you to adopting one of the following techniques to achieve your goal:
- Use a Server Side Proxy
- Use JSONP (if the remote API supports it)
I will leave the JSONP technique for another day and get to my subject now. The W3C made CORS (Cross Origin Resource Sharing) a Recommendation in January 2014, a document that was in the works for some time now.
The CORS Recommendation allows a way around for web servers to allow for cross domain script requests. Servers can now do this by adding new headers in the HTTP response to a cross domain request, namely:
1 |
Access-Control-Allow-Origin: <domain> | * |
By sending this new header, the server can let the browser making the request know that it can allow the request and response to be used by the script, and hence not block the request. You can read more details about the CORS spec on W3.org and MDN. This is great for API developers who want to make a service available for consumption from simple Ajax requests from any domain.
I will jump to my demo now. http://sreenath.net/demos/CORSDemo.htm
To demonstrate this, I use the OpenWeatherMap’s REST API to provide me the cross domain content. And I use a standard XMLHttpRequest object pointed to the Open Weather Map API’s URL for retrieving the current weather data for the requested city.
For example, if I want to get the current weather conditions of New York, NY, my XHR’s URL will look like this:
1 |
http://api.openweathermap.org/data/2.5/weather?q=New%20York,%20NY |
and my request headers (on chrome) look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
GET /data/2.5/weather?q=New%20York,%20NY HTTP/1.1 Host: api.openweathermap.org Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36 Origin: http://sreenath.net Accept: */* DNT: 1 Referer: http://sreenath.net/demos/CORSDemo.htm Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,kn;q=0.6 |
And the response headers from the server look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
HTTP/1.1 200 OK Server: nginx Date: Mon, 28 Apr 2014 02:03:28 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, POST |
Yep, a 200 OK response alright. And since I didn’t specify a format, I would receive the default JSON format from the server containing the current weather conditions.
Observe the last three response headers. They are all from the CORS spec and there are more. To go deeper into this topic, Monsur Hossain has published a book “CORS In Action“, available Sept 2014 in print or now through MEAP. You can also visit Enable CORS website to get updated information and use this link to know about browser support for this new spec.
With ASP.NET Web API where it currently is, this development greatly enhances the idea of Service Oriented Applications and also emphasizes the role of JavaScript in the world of programming today. Get cracking!
Questions? Comment below ↓