Home  »  Solutions  »  How to Make Simple Cross-Domain Ajax Requests With Responses

How to Make Simple Cross-Domain Ajax Requests With Responses

Nate Weiner - Posted in Solutions, , , Comments (5)

For Read It Later for the iPhone, I built a ‘Tap to Save’ bookmarklet for Mobile Safari.  When using Tap to Save, instead of opening a link when clicked, the link is saved to a user’s reading list.  This makes it easy to save a few links from a web page without having to open each one individually.

The problem I came across however was I could not do an ajax request to send the link to the Read It Later server because cross-domain browser restrictions.

I could use an iframe to send the request, but again because of cross-domain issues, I would not be able to retrieve a response from inside of it.  After the request was sent, there were 3 possible outcomes: Success, the user needs to login, or there was a problem saving.

The method that eventually dawned on me is rather hackish, but it works none-the-less.  It provides a way to send a request to any domain and get a basic response.

The solution: Images are not subject to cross domain restrictions.  So load an ‘image’ with a get string that hits a script on the server and then returns an different sized image per possible outcome.

If that makes absolutely no sense, let me try to illustrate with an example that provides a response with two options: success/failure.

Starting the Request: (Javascript: Client Side)

// Load an image pointing to your script
ajaxImg = new Image();
ajaxImg .src = ‘http://myserver.com/script.php?myvariables=1&foo=bar’;
document.body.appendChild(ajaxImg);

// Start a timer to check if the image has loaded
ajaxTimer = setInterval(’isImageLoaded()’, 250);

Handling the Request (Server Side):

The image is now loading this script:

<?php

/* ... do your request processing here ... */

// Based on the result of the script, we either return a
// 1px wide image (in the case of success) or
// 2px wide image (in the case of failure)
// you'll need to create these images yourself

if ($success) {
        $file = file_get_contents( '1x1.gif' );
} else {
        $file = file_get_contents( '2x1.gif' );
}

// output the image
$length = strlen($file);
header('Last-Modified: '.date('r'));
header('Accept-Ranges: bytes');
header('Content-Length: '.$length);
header('Content-Type: image/gif');
print($file);

?>

Handling the Response: (Javascript: Client Side)

Back on the javascript side of things, we have our ajaxTimer checking to see if the image is loaded. Once the image loads, we’ll check the width.


function isImageLoaded() {
     if (ajaxImg.complete) {

         var w = ajaxImg.width;
         if (w == 1) {
              alert('Success!');
         } else if (w == 2) {
             alert('Failed!');
         }

         // Hide the image (even though you probably won't see it
        ajaxImg.style.display = 'none';

        // Stop the timer
        clearInterval(ajaxTimer);

     }
}

Simple Works Best

As you can see, this works well if you only have a few possible outcomes of the transaction or if you do not need to return a literal response like generated markup.

IE Woes

Surprisingly, this DOES work in IE6 and IE7, however there is a little bit of extra work. The url of the request you load into the src of the image has to have .gif in it. For example: ’script.php’ won’t work, but ’script.gif’ will. So to make this work you’ll need to add an Htaccess rewrite rule to redirect the script.gif to your script.php file.

RewriteRule ^script.gif$ script.php [QSA=%{QUERY_STRING}]

Comments (5)


  1. flXHR (http://flxhr.flensed.com) is a client-side proxy for cross-domain Ajax requests. It allows you to make simple, standard XHR calls, but do so cross-domain just like regular Ajax.

    flXHR has an identical API to native XHR, which makes it very easy to drop in and use in existing projects. It also has plugins for many of the major frameworks, which allows even easier integration and functionality.

    July 23rd, 2009 Kyle Simpson
  2. Totally cool! Good “outside of the box” thinking.
    I knew there was a way to do this and knew it would be simple! :-)

    Pros: Browser vendors can’t plug this as security vulnerability since plugging it would break the web.

    Cons: Bad folks will use it for nefarious deeds - assuming they’re not already doing so.

    November 17th, 2009 dgreenhouse
  3. Thanks for this, it was exactly what I needed for a script, but moreover it cleared up my confusion as to why other tracking scripts used something similar

    December 8th, 2009 Jon
  4. I was stuck on the cross domain ajax request matter too.
    I resolved only using a proxy JSP between my server and clients.
    Now the ajax calls are sent to the jsp that is in my domain and handle the data transfer with the server.

    By the way: great work with the Read It Later app. I’m going to upgrade to Pro version today.

    December 14th, 2009 Alessandro Mazzega
  5. Absolutly brilliant ! It makes me dream about creating a class that would allow to even exchange more complex data, like a string of ten chars for example, encoded with 3 or 4 images having different width and height.
    Something you might add to your article is the fact that in php, you really should echo some header that prevent caching ! cause image are very likely to be cached if you dont take care of it, and that would just ruin the functionality you created.
    Again, genius idea man !

    July 6th, 2010 miracl

Leave a Reply