the Future of the Web
  • Home
  • Articles
  • Contact
  • Cross-Domain JSON without XHR

    Aug 11 2006

    I was just reading on the Ajaxian a quote from an article Why XHR should become opt-in cross-domain, so I started thinking, isn't there a way around this already?

    A quick explanation of what I'm talking about: XMLHttpRequest (the function behind Ajax) will only let you connect to URLs on the same domain as the page you're on. This means the Ajax happening on xyz.com can only connect to URLs on xyz.com. Even if XYZ wanted to use Ajax to pull some data from foobar.com, they wouldn't be able to.

    Now there is already one popular way around this. You can make a proxy page that gets the data for you. Using the same example, XYZ could make a URL like xyz.com/json_proxy that pulled data over from foobar.com behind the scenes, thus making the foobar.com data available on xyz.com. The problem with this is, XYZ would have to handle double the bandwidth of this data unnecessarily. This can be a big problem for smaller companies.

    I have an alternative solution to this problem. Instead of using XMLHttpRequest to load the data, we can just use <script> tags instead. These don't have the same cross-server restrictions as XMLHttpRequest. In fact, this is how Adsense works. You stick a <script> tag on the page which executes JavaScript coming from Google's server, and this writes out the ads on the page.

    To add a <script> tag to our page, we only need to call this function:

    function addScript(url) {
        var script = document.createElement('script');
        script.src = url;
        document.body.appendChild(script);
    }

    If we have a URL that returns some JSON data, we just pass that URL to this function and the page will load that data. Well, not entirely. There's a few things we need to do different. With JSON, you have some data like:

    {
       "firstname": "Jesse",
       "lastname": "Skinner"
    }

    and then use XMLHttpRequest with eval() to assign it to a variable. If you just stuck a script tag on the page to load this, nothing would happen. It would just load and the JavaScript parser would say "Great, nice little piece of data." But it's not going to assign it to a variable, so you'll have no way to access it.

    There's actually no way around this unless you change what is returned by the JSON data URL. This is the special trick. We would need the JavaScript to execute some function or assign the data to a variable. It would need to look like this:

    json_callback({
       "firstname": "Jesse",
       "lastname": "Skinner"
    });

    Now, we just need to make a simple function called json_callback() that takes the data and does something with it. Voila! Cross-server JSON.

    Rather than hardcode some callback function name, it would probably be better to add an optional "callback" parameter that would specify the function name. If the callback parameter is missing, the server can return standard ol' JSON.

    Let's say our simple JSON example above came from "foobar.com/data?format=json". If example.com was kind enough to provide this flexibility, they could add the parameter so that "foobar.com/data?format=json&callback=my_json_callback" formats the data as a function call, passing the data object to my_json_callback().

    Now, we just need to wait for web APIs with JSON to start supporting this parameter.

    Update: I've since discovered that Yahoo!'s JSON API already provides a 'callback' parameter exactly as I've described above, and I suspect that other APIs out there may support this as well. Either I'm psychic or there are time travellers working at Yahoo! ;) Here are the details from Yahoo!

    Tags: javascript xmlhttprequest json
    View 6 Comments | Add a comment
  • Comments

    1. Peter Nixey at 6:51am on August 11, 2006

    Hi Jesse,

    Thanks for your response to my article and your technique is spot on. The issue I was highlighting though is that whilst cross-domain JSON is a solution to the data-access problem, it's very insecure and dangerous.

    We can get it but we have to give the other server complete access to our webpages in the process.

    2. Jesse Skinner at 7:03am on August 11, 2006

    Hey Peter,

    Yes, I agree, this method is certainly not secure. In a sense, allowing the 'callback' parameter is similar to giving a header of 'Cross-domain-access: true'. As with the header, you would have to be careful which data you exposed cross-domain. del.icio.us bookmarks might be okay, but I sure wouldn't want my gmail inbox exposed.

    3. Pat at 12:18am on June 25, 2008

    Dude, This article saved my life.

    I ended up inserting my .js files using this code:

    var headElement = $doc.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.language="javascript";
        script.src = url;
        headElement.appendChild(script);

    Later I referenced them using:

    return $wnd[varName];

    This is all probably pretty simple stuff to javascript experts.

    4. Chris at 8:37pm on July 14, 2009

    For anyone stumbling across this article, Google's json also supports a callback
    http://code.google.com/apis/gdata/json.html#Request

    5. Yogi at 2:04pm on September 2, 2009

    This approach uses "GET" to get content. Since browser has some limitation on URL length using get, it fails for larger data. Can we some how use POST to achieve same result.

    6. Jesse Skinner at 2:11pm on September 2, 2009

    @Yogi - Long story short, no you can't.

    You can submit a form to another domain using a hidden iframe, but you cannot get a response back from that domain (or see if it fails), which may work for some purposes.

    Alternatively, you can try splitting up the data into multiple requests, each under 2kb or 4kb or whatever URL limit you're trying to stay within.

    Add a Comment

    Note: HTML tags and entities will be converted so that they are displayed as you type them. This means if you type in <em>, people will see <em>, and if you type &lt;em&gt;, people will see &lt;em&gt;.

  • Request a Quote

  • Jesse Skinner

    Jesse Skinner
    • About Me
    • Email Me
    • RSS Feed RSS Icon
    • @JesseSkinner
  • Recent Articles

    • jQuery Live Events
    • I need web developers
    • buttons need type="submit" to submit in IE
    • Win $200 in a Web Dev Writing Contest
    • Use Arrays in HTML Form Variables
    • 5 Reasons Freelancers Can Succeed in a Shrinking Economy
    • Keeping a Live Eye on Logs
    • Using PHP's empty() Instead of isset() and count()
    • Testing Web Pages with Lynx
    • Stop CSS Background Flickering in Internet Explorer 6
    • See All...
  • Categories

    • javascript (39)
    • links (21)
    • about (19)
    • web (14)
    • html (12)
    • server (11)
    • css (8)
    • browsers (8)
    • carnival (7)
    • work (6)
    • design (4)
    • seo (4)
    • ads (4)
    • standards (4)
    • events (4)
  • Older Articles

    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
    • July 2008
    • June 2008
    • May 2008
    • April 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • September 2007
    • August 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    • March 2007
    • February 2007
    • January 2007
    • December 2006
    • November 2006
    • October 2006
    • September 2006
    • August 2006
    • July 2006
    • June 2006
    • May 2006
    • April 2006
    • March 2006
    • February 2006
    • January 2006
    • December 2005
    • November 2005
    • October 2005
    • September 2005
    • August 2005
    • April 2005
    • See All...
Copyright © 2010 The Future of the Web