AJAX cross domain call

142,229

Solution 1

The only (easy) way to get cross-domain data using AJAX is to use a server side language as the proxy as Andy E noted. Here's a small sample how to implement that using jQuery:

The jQuery part:

$.ajax({
    url: 'proxy.php',
    type: 'POST',
    data: {
        address: 'http://www.google.com'
    },
    success: function(response) {
        // response now contains full HTML of google.com
    }
});

And the PHP (proxy.php):

echo file_get_contents($_POST['address']);

Simple as that. Just be aware of what you can or cannot do with the scraped data.

Solution 2

You will need to dynamically insert a script tag into the page that references the data. Using JSONP, you can execute some callback function when the script has loaded.

The wikipedia page on JSONP has a concise example; the script tag:

<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>

would return the JSON data wrapped in a call to parseResponse:

parseResponse({"Name": "Cheeso", "Rank": 7})

(depending on the configuration of the getjson script on domain1.com)

The code to insert the tag dynamically would be something like:

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);

Solution 3

You can use YQL to do the request without needing to host your own proxy. I have made a simple function to make it easier to run commands:

function RunYQL(command, callback){
     callback_name = "__YQL_callback_"+(new Date()).getTime();
     window[callback_name] = callback;
     a = document.createElement('script');
     a.src = "http://query.yahooapis.com/v1/public/yql?q="
             +escape(command)+"&format=json&callback="+callback_name;
     a.type = "text/javascript";
     document.getElementsByTagName("head")[0].appendChild(a);
}

If you have jQuery, you may use $.getJSON instead.

A sample may be this:

RunYQL('select * from html where url="http://www.google.com/"',
       function(data){/* actions */}
);

Solution 4

Unfortunately (or fortunately) not. The cross-domain policy is there for a reason, if it were easy to get around it then it wouldn't be very effective as a security measure. Other than JSONP, the only option is to proxy the pages using your own server.

With an iframe, they are subject to the same policy. Of course you can display the data from an external domain, you just can't manipulate it.

Solution 5

I use this code for cross domain ajax call, I hope it will help more than one here. I'm using Prototype library and you can do the same with JQuery or Dojo or anything else:

Step 1: create a new js file and put this class inside, I called it xss_ajax.js

var WSAjax = Class.create ({
    initialize: function (_url, _callback){
        this.url = _url ;
        this.callback = _callback ;
        this.connect () ;
    },
    connect: function (){
        var script_id = null;
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', this.url);
        script.setAttribute('id', 'xss_ajax_script');

        script_id = document.getElementById('xss_ajax_script');
        if(script_id){
            document.getElementsByTagName('head')[0].removeChild(script_id);
        }

        // Insert <script> into DOM
        document.getElementsByTagName('head')[0].appendChild(script);
    },
    process: function (data){
        this.callback(data) ;
    }

}) ;

This class creates a dynamic script element which src attributes targets your JSON data provider (JSON-P in fact as your distant server must provide the data in this format :: call_back_function(//json_data_here) :: so when the script tag is created your JSON will be directly evaled as a function (we'll talk about passing the callback method name to server on step 2), the main concept behind this is that script like img elements are not concerned by the SOP constraints.

Step2: in any html page where you wanna pull the JSON asynchronously (we call this AJAJ ~ Asynchronous JAvascript + JSON :-) instead of AJAX which use the XHTTPRequest object) do like below

//load Prototype first
//load the file you've created in step1


var xss_crawler = new WSAjax (
     "http://your_json_data_provider_url?callback=xss_crawler.process"
 ,   function (_data){
            // your json data is _data and do whatever you like with it 
        }) ;

D'you remenber the callback on step 1? so we pass it to the server and it will returns the JSON embeded in that method so in our case the server will return an evalable javascript code xss_crawler.process(//the_json_data), remember that xss_crawler is an instance of WSAjax class. The server code depends on you (if it's yours), but most of Ajax data providers let you specify the callback method in parameters like we did. In Ruby on rails I just did

render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"

and that's all, you can now pull data from another domain from your apps (widgets, maps etc), in JSON format only, don't forget.

I hope it was helpfull, thanks for your patience :-), peace and sorry for code formatting, it doesn't work well

Share:
142,229
jAndy
Author by

jAndy

Frontend Engineer Public CV: http://careers.stackoverflow.com/jandy Contact: [email protected] Playground: CodePen Remembering that I'll be dead soon, is the most important tool I've ever encountered to help me make the big choices in Life. Because almost everything - all external expectations, all pride, all fear of embarrassment or failure, these things just fall away in the face of death, leaving only what is truly important. Remembering that you are going to die, is the best way I know to avoid the trap of thinking you have something to lose. You are already naked, there is no reason not to follow your heart. -- Steve Jobs

Updated on June 01, 2020

Comments

  • jAndy
    jAndy almost 4 years

    I know about AJAX cross-domain policy. So I can't just call "http://www.google.com" over a ajax HTTP request and display the results somewhere on my site.

    I tried it with dataType "jsonp", that actually would work, but I get a syntax error (obviously because the received data is not JSON formated)

    Is there any other possiblity to receive/display data from a foreign domain? iFrames follow the same policy?

  • Andy E
    Andy E about 14 years
    @Nir: He gets the syntax error because he's fetching HTML, not JSON. This will never work with JSONP :-)
  • jAndy
    jAndy about 14 years
    would this only work if you receive JSON data or with plain text or HTML aswell?
  • Andy E
    Andy E about 14 years
    @jAndy: This will work for JSONP (including the callback function) data only.
  • jAndy
    jAndy about 14 years
    what do you mean by, "you just can't manipulate it" ? You can't load some data into an iFrame and read that data over a jQuery selector for instance?
  • Andy E
    Andy E about 14 years
    @jAndy: No, access is blocked to 99% of the DOM when accessing documents across different domains. Cross-document messaging is possible (with HTML5/modern browsers), but it has to be implemented by both sides.
  • Darin Dimitrov
    Darin Dimitrov over 13 years
    you are not dooming your users to HTML5 browsers, you are making them a service :-)
  • Christian Studer
    Christian Studer over 13 years
    And be very much aware that such a proxy is a severe security hole... At least make a list of acceptable addresses and don't just blindly accept any passed address. Have a look at a decent proxy script here: benalman.com/projects/php-simple-proxy
  • Mori
    Mori over 10 years
    But doesn't it break the layout when the target page has non-absolute URLs and relative links?
  • ProblemsOfSumit
    ProblemsOfSumit over 8 years
    only works for GET requests. No PUT, DELETE or POST. So no RESTful interface.
  • John
    John almost 8 years
    @ChristianStuder Why is this problematic?