Over the holidays I had a chance to talk to some of my old compadres from the XML team at Microsoft and we got to talking about the JSON as an alternative to XML. I concluded that there are a small number of key reasons that JSON is now more attractive than XML for kinds of data interchange that powers Web-based mashups and Web gadgets widgets. This is the first in a series of posts on what these key reasons are.

The first "problem" that chosing JSON over XML as the output format for a Web service solves is that it works around security features built into modern browsers that prevent web pages from initiating certain classes of communication with web servers on domains other than the one hosting the page. This "problem" is accurately described in the XML.com article Fixing AJAX: XMLHttpRequest Considered Harmful which is excerpted below

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.

This restriction is a significant annoyance for Web developers because it eliminates a number of compelling end user applications due to the limitations it imposes on developers. However, there are a number of common workarounds which are also listed in the article

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:

  1. 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.
  2. 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.
  3. Script tag hack with application proxy (doesn't use XMLHttpRequest at all). Use the HTML script tag to make a request to an application proxy (see #1 above) that returns your data wrapped in JavaScript. This approach is also known as On-Demand JavaScript.

Although the first two approaches work, there are a number of problems with them. The first is that it adds a requirement that the owner of the page also have Web master level access to a Web server and either tweak its configuration settings or be a savvy enough programmer to write an application to proxy requests between a user's browser and the third part web service. A second problem is that it significantly increases the cost and scalability impact of the page because the Web page author now has to create a connection to the third party Web service for each user viewing their page instead of the user's browser making the connection. This can lead to a bottleneck especially if the page becomes popular. A final problem is that if the third party service requires authentication [via cookies] then there is no way to pass this information through the Web page author's proxy due to browser security models.

The third approach avoids all of these problems without a significant cost to either the Web page author or the provider of the Web service. An example of how this approach is utilized in practice is described in Simon Willison's post JSON and Yahoo!’s JavaScript APIs where he writes

As of today, JSON is supported as an alternative output format for nearly all of Yahoo!’s Web Service APIs. This is a Really Big Deal, because it makes Yahoo!’s APIs available to JavaScript running anywhere on the web without any of the normal problems caused by XMLHttpRequest’s cross domain security policy.

Like JSON itself, the workaround is simple. You can append two arguments to a Yahoo! REST Web Service call:

&output=json&callback=myFunction

The page returned by the service will look like this:

myFunction({ JSON data here });

You just need to define myFunction in your code and it will be called when the script is loaded. To make cross-domain requests, just dynamically create your script tags using the DOM:

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '...' + '&output=json&callback=myFunction';
document.getElementsByTagName('head')[0].appendChild(script);

People who are security minded will likely be shocked that this technique involves Web pages executing arbitrary code they retrieve from a third party site since this seems like a security flaw waiting to happen especially if the 3rd party site becomes compromised. One might also wonder what's the point of browsers restricting cross-domain HTTP requests if pages can load and run arbitrary Javascript code [not just XML data] from any domain.

However despite these concerns, it gets the job done with minimal cost to all parties involved and more often than not that is all that matters.

Postscript: When reading articles like Tim Bray's JSON and XML which primarily compares both data formats based on their physical qualities, it is good to keep the above information in mind since it explains a key reason JSON is popular on the Web today which turns out to be independent of any physical qualities of the data format. 


 

Categories: Web Development | XML | XML Web Services
Tracked by:
http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=39842a17-781a-45c8-ade5-58... [Pingback]
http://just.shelleypowers.com/juststuff/dare-to-stay/ [Pingback]
http://sitecore.alexiasoft.nl/2007/01/02/json-in-the-news/ [Pingback]
http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=d639d908-7fbc-40cd-8e36-e6... [Pingback]
http://blogs.msdn.com/peterlau/archive/2007/01/04/dare-obasanjo-discusses-how-br... [Pingback]
http://blogs.msdn.com/dancre/archive/2007/01/04/web-security-is-hard.aspx [Pingback]
http://wpf.netfx3.com/blogs/wpf_community_bloggers/archive/2007/01/05/web-securi... [Pingback]
http://slashstar.com/blogs/tim/archive/2007/01/05/json-and-xml.aspx [Pingback]
http://blogs.nitobi.com/dave/?p=178 [Pingback]
http://www.ajaxgirl.com/2007/01/04/json-vs-xml-the-debate/ [Pingback]
http://utlf9fi.net/03/index.html [Pingback]
http://zabivwn.net/alaska/sitemap1.html [Pingback]
http://weujmru.net/housing/sitemap1.html [Pingback]
http://weujmru.net/activities/sitemap1.html [Pingback]
http://yftbsy1.net/lottery/sitemap1.html [Pingback]
http://vy3i7wz.net/leather/index.html [Pingback]
http://blogger/cs/blogs/mconly/archive/2008/03/12/GeoJSON-_2D00_-there_2700_s-a-... [Pingback]
http://ukpuuq8.net/housing/sitemap1.html [Pingback]
http://tb9wlm3.net/12/index.html [Pingback]
http://ofiyspg.net/sitemap1.html [Pingback]
http://eofw1lk.net/connecticut/sitemap1.html [Pingback]
http://box405.bluehost.com/~dugablog/sitemap2.html [Pingback]
http://rogents.netfirms.com [Pingback]
http://tulanka.readyhosting.com/online/sitemap1.php [Pingback]
http://tulanka.readyhosting.com/car/sitemap1.php [Pingback]
http://biggest-hosting10.com/~rocata/furniture/index.html [Pingback]
http://restablog.dreamhosters.com/photo/sitemap1.html [Pingback]
http://host239.hostmonster.com/~blogford/sitemap2.html [Pingback]
http://gator413.hostgator.com/~digital/loan/sitemap1.html [Pingback]
http://gator413.hostgator.com/~digital/shoes/sitemap1.html [Pingback]
http://bbgicfz.net/sitemap1.html [Pingback]
http://st9odlg.net/arkansas/sitemap1.html [Pingback]
http://jz0uott.net/sofa/index.html [Pingback]
http://lt5d7yk.net/sitemap1.html [Pingback]
http://kmnjey0.net/dental/sitemap1.html [Pingback]
http://ik6bcb7.net/sitemap1.html [Pingback]
http://d579737.u108.floridaserver.com/sitemap1.html [Pingback]
http://gator442.hostgator.com/~hockteam/lottery/sitemap1.html [Pingback]
http://gator442.hostgator.com/~hockteam/southwest/sitemap1.html [Pingback]

Tuesday, January 2, 2007 6:42:24 PM (GMT Standard Time, UTC+00:00)
JSON itself doesn't introduce this security hole. What you describe is a security risk because you're executing arbitrary JavaScript code from a (potentially untrustworthy) third party. If you're not using "On-Demand JavaScript" (also known as "JSON with Padding" or JSONP), then you'll be using XMLHttpRequest and be subject to the browser's same-origin policy.

Since the data is then coming from your own server, it's safe to eval() the result from JavaScript. Of course, if you use a server-side proxy to third-party JSON, then you need to validate it first before eval-ing. (Valid JSON contains only data.) This could be done either on the server or on the client.
Tuesday, January 2, 2007 7:17:32 PM (GMT Standard Time, UTC+00:00)
To elaborate on what Steve Marx wrote, the design pattern (scary as it is) is in no way intrinsic to JSON -- it could just as easily be used with XML. Just pass a string containing XML markup as the argument to myFunction() in the returned script, instead of passing JSON. With a bit of work, you could even pass a DOM node as the argument.

(BTW, I had included some examples, but they kept crashing your /webapp application with security warnings.)
Tuesday, January 2, 2007 8:04:15 PM (GMT Standard Time, UTC+00:00)
The security risk of cross-domain XMLHttpRequest should also be clarified. One of the primary risks is that it enables a malicious third party to spider behind firewalls.

Cross-domain posting would be great but I'm not sure how the best way to provide it with minimal risk.
pwb
Tuesday, January 2, 2007 10:29:24 PM (GMT Standard Time, UTC+00:00)
Hey Dare, I'm glad you're blogging.

This is the point I was trying to make in my comments to your "Widgets Become More Important than APIs for Data Exchange on the Web" article (http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=55b58719-a06b-445e-aa96-b5d395cbdf75) I don't think I did as good a job as you did however. :)

I like to think of the del.ico.us widget as a nice default implementation of their "On-Demand JavaScript". But you can still use the JavaScript without the widget. It makes life easier because the format is very close to the JavaScript I would have built on the server-side using their API. (I'd put the del.ico.us stuff in a separate JavaScript file so I could cache the del.ico.us stuff independently of the page it was running on.)
Thursday, January 4, 2007 3:36:43 PM (GMT Standard Time, UTC+00:00)
Hi,

what you are basically saying is that the "same-origin-policy" is bad for mashup style applications...well agreed.

But removing this policy is a serious security risk. Websites can transfer code on your machine that spiders/attacks other internal/external servers. There is a reason for this limitation.

ASP.NET AJAX has (had?) the web service bridge to make these scenarios easier - and thats the right approach IMO.

dominick
Friday, January 5, 2007 1:00:05 PM (GMT Standard Time, UTC+00:00)
Another option:

"Cross Domain XMLHttpRequest using an IFrame Proxy"
See: http://manual.dojotoolkit.org/WikiHome/DojoDotBook/Book75
Bill Higgins
Comments are closed.