Cross-Domain AJAX calls using PHP

Mar 6, 2008

AJAX has become the core component of many web applications around us. And its fairly easy to handle AJAX now a days, with the help of various javascript libraries (ex: jQuery, Prototype, Mootools, YUI, etc). But there is one security issue that web browsers impose in doing AJAX calls – they don’t let you do AJAX calls in web servers different than yours. That means, if your script is in www.mydomain.com and you’re trying to do AJAX call to www.anotherdomain.com/get.php, then the browser will through error like: “Error: uncaught exception: Permission denied to call method XMLHttpRequest.open”.

Now, there are a number of solutions to this problem. Instead of explaining them all to you, lemme provide you the simplest one: using a PHP transport file. If you already know the thing and just need the script, download from here.

Others, let’s see an example implementation first.

Example use

   1: xmlHttp.onreadystatechange=function()
   2: {
   3:     if(xmlHttp.readyState==4)
   4:     {
   5:         alert(xmlHttp.responseText);
   6:     }
   7: }
   8:  
   9: xmlHttp.open("GET", 'http://myserver.com/transport.php?action=' + 
  10:                     urlencode('different-server.com/return_call.php') +
  11:                     '&method=get&data1=101&data2=pass', true );
  12:  
  13: xmlHttp.send(null);

Now, lets see how it works:

  1. The script makes an AJAX call to the myserver.com/transport.php with a few parameters:
    • action = the target URL you need to fetch, from a different domain
    • method = the HTTP method (post/get)
    • data1, data2 = sample parameters for using as either query-string or POST fields
  2. When the request is received by transport.php, it uses cURL to make a call to the page mentioned in action.
  3. Based on the method, it either makes a GET request or a POST request. In both cases, it sends the extra parameters that are sent.
  4. After the response is received, transport.php echoes it. So, you have what you need!

Download

transport.php
Cross-Domain AJAX call transporter.
Downloaded: times

Comments and suggestions are most welcomed :)

There are 22 comments in this article:

  1. 6/03/2008Loïc Hoguin says:

    Please please please add some caching mechanism to your script. You do not want to allow some kiddie to flood another website using your script. Even 1-minute cache is enough, but just don’t call this website everytime like this. Not only will it be slow but the other site owner might get angry at you.

  2. 6/03/2008H2 says:

    Does it also support POST simulation?

    Good Work Batman!

  3. 6/03/2008Emran Hasan says:

    @H2: Of course. Thanks !

  4. 6/03/2008Saidur Rahman says:

    This is a nice tutorial with explanation. Well I want t o show if you want to use jquery (http://jquery.com/).

    If you want to get json data , then you can easily use getJSON.

    $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?",
         function(data){
              $.each(data.items, function(i,item){
                   $("").attr("src", item.media.m).appendTo("#images");
         });
    });

    Or if you don’t want to get other type of data like XML or other type, then you have to use cURL in PHP:

    $.ajax({
         type:   "GET",
         url :     ”http://myserver.com/transport.php?action=’ +
                   urlencode(‘different-server.com/return_call.php’) +
                   ‘&method=get&data1=101&data2=pass”,
         success: function(serverResponse)
              /*parse serverResponse data    */
    });
  5. 6/03/2008zack says:

    I think that Loic Hoguin’s recommendation is accurate.
    No comment ?

  6. 6/03/2008Emran Hasan says:

    @Loic Hoguin: I completely agree with you that this script shouldn’t allow other person from web to misuse it for their own use.

    But I would suggest using $_SERVER['REMOTE_ADDR'] to block request from scripts other than the server I’m invoking it from.

    The reason I think that way is, in the project I used it, the other server was also mine and I needed to communicate between them. As the output was quite dynamic, caching couldn’t be done.

    But then again, if needed, caching can be added easily. I will be uploading one with caching later tonight.

    Thanks everybody for commenting !

  7. 6/03/2008Loïc Hoguin says:

    Indeed, filtering using REMOTE_ADDR is the best if both servers are yours.

    What’s important to note, too, is that if curl_exec can’t fetch the data for some reasons it will return false. That means that your script will echo nothing. People using it should take care on the javascript side to check the data they get and if it’s empty display an error.

  8. 7/03/2008Emran Hasan says:

    @Loic Hoguin: Yes, you’re right. Also, to be safe, using a http wraper class supporting both cURL and fsockopen (like mine one) can be suggested to avoid problem.

  9. 26/03/2008SuNcO says:

    On the transport file you can’t get the action because is named url

    You must change that line :

    $action = $_REQUEST['url'];

    To :

    $action = $_REQUEST['action'];

    Or change this :

    xmlHttp.open(“GET”, ‘http://myserver.com/transport.php?action=’ + 10: urlencode(‘different-server.com/return_call.php’) + 11: ‘&method=get&data1=101&data2=pass’, true );

    With this :

    xmlHttp.open(“GET”, ‘http://myserver.com/transport.php?url=’ + 10: urlencode(‘different-server.com/return_call.php’) + 11: ‘&method=get&data1=101&data2=pass’, true );

  10. 7/04/2008François Labarde says:

    there’s a typo:

    you wrote this:
    if ($key != ‘url’ || $key != ‘method’)

    while you obviously meant this:
    if ($key != ‘url’ && $key != ‘method’)

    (since ($key != ‘url’ || $key != ‘method’) is always true)

  11. 6/05/2008Kelvin says:

    I have tried this proxy approach, but neither Firefox nor IE 6 will allow me to call a php page with XMLHttpRequest. Of course, it won’t allow me to call webservice cross-domain either.
    Thanks.

  12. 16/09/2008Learning: XMLHttpRequest » alex.mullr.net/blog by Alex Muller says:

    [...] hosting and don’t have access to the server configuration, I’m going to try doing it via PHP. This LiveJournal post is also applicable to the [...]

  13. 25/09/2008Rene Veerman says:

    Hi, i’ve tried using your script and on my homeserver it runs fine but on my shared hoster it hangs at curl_exec().
    Is there anything you know of that causes this freezing/hanging?

  14. 27/04/2010Mckenzie's hima time » cross domain scripting says:

    [...] Emran produced an excellent example. This is a php based example here: [...]

  15. 14/05/2010George Arthur says:

    Emran, I never leave comments -so take this as the highest compliment I can give. Thank you for your transfer.php. For six months i have tried to cross-domain. I tried the all CD scripts, ACD.js ….etc. Your script works! and i’m not sure why or how. As a dummy compared you folks, you may be interested in my implementation (don’t laugh):

    I got the standard function ajax(loadjava,url, containerid, jss1, jss2, jss3) from DynamicDrive.com and downloaded your transfer.php Here’s my working htm:

    test google.com

    And it works! I can use js to read and parse. This solves a huge problem i’ve had with two webs that need to communicate with each other.

    Emran Hasan, I will not forget your name. Thanks, George

  16. 14/05/2010Emran Hasan says:

    @George: Thanks very much for your compliments and I am glad my script worked for you :) Feel free to get in touch whenever you need help with web.

  17. 15/08/2010Jose says:

    Hi Emran,

    I found your script interesting, really.
    But I can see one problem, correct me please, if I am wrong.

    Using transport.php, will do that the query is fired from the server side, instead of from the browser (client side), and then we’re missing focus on the Ajax philosophy, which intend is to execute the code at the client, and not at the server.

    Do you agree?

    Best wishes.

  18. 12/04/2011selva says:

    The download link is not working

  19. 26/07/2011Ben says:

    Yea, same here: The page you are looking for doesn’t exist. Sorry. :(

  20. 18/08/2011Rajan says:

    Download link is not working.. give me updated one…

  21. 18/09/2011Kyle Laurich says:

    A person made a few decent factors there. I looked on the net for the matter and discovered most individuals will accompany with your website Cross-Domain AJAX calls using PHP | Emran Hasan's Blog.

  22. 4/10/2011Ajax call from external domain « Codeperl's Knowledge Sharing System says:

    [...] http://phpfour.com/blog/2008/03/cross-domain-ajax-using-php/Like this:LikeBe the first to like this post.   [...]

Write a comment: