How-to make cross-domain URL call work in javascript

I was quite busy in the past 2014. I only wrote one blog post in the whole year. Busy is a good excuse for lazy :). I hope I can post more in 2015 to help others and help me as well.

In my first post this year, I’ll share my experiences with cross domain URL call in JavaScript.

Case 1. Normal URL call with JQuery

url = "https://alexzeng.wordpress.com/api/report/";    
$.get(url, function(data) {
    //process data;
    process(data);
});

Case 2. Cross-domain URL call with JQuery
Just add a parameter “callback” with value “?” in your URL, JQuery will handle everything else.

url = "http://alezeng.blogspot.com/api/report/";
$.getJSON(url + "?callback=?", function (result) {
    // process data
    process(data);
}); 

Note: if your url already have some prarameters, use “&” to connect callback parameter like “&callback=?”

There’re some pre-requirements on the API at server side:
1. The API should return the data with “Content-Type:text/javascript”. Otherwise this error’ll show in javascript call:

Resource interpreted as Script but transferred with MIME type text/html

You can check the “Content-Type” in Response Headers by manually call the url in Chrome debug mode.

2. The API should handle the callback parameter, and wrapper the data in callback function. Otherwise you’ll get error because it cannot run as a javascript function
Many RESTful API using modern framework can support by default, for example Django, Spring MVC. But if you use an old framework or home-grown API, or even just a statistic text, it won’t work by default.
However, if you understand how it works, you can mimic what it does and make it work for any URL. Let’s practice it in Case 3.

Case 3.  Manually call Cross-domain URL
Scenario:
I have data at http://alezeng.blogspot.com/api/report.dat.
I want to use the data it in my another site https://alexzeng.wordpress.com/
Step 1. Wrapper data in a callback function
http://alezeng.blogspot.com/api/report.dat, content:

my_callback({
   'key1' : 'value1',
   'key2' : 'value2'
})

Note: you can enclose any value in my_callback as long as it’s a valid javascript parameter.

Step 2. Make your server response the URL as javascript.
In my case, apache is my web server. It’ll return the data as “Content-Type:text/html” by default.
Add below line in apache config file to let it response “.dat” as javascript:

AddType text/javascript .dat 

Note: if the URL is a RESTful API, wrote by programming language, like java or python, you can set the response content type in code directly.

Step 3. Write the callback function
In another site https://alexzeng.wordpress.com/, write javascript codes to handle the data:

function my_callback(data)
{
    //process data
    process(data);
}

function cross_domain_call() {
    url = 'http://alezeng.blogspot.com/api/report.dat'    
    var script = document.createElement('script');
    script.src = url +'?callback=my_callback'
    document.getElementsByTagName('head')[0].appendChild(script);
}

With this, we can successfully get the data from http://alezeng.blogspot.com in https://alexzeng.wordpress.com.
But it’s kind of troublesome if you have any URL that need to change at server side. The other way is, we can use our server to call cross-domain URL on behalf of client.

Case 4. Use server to call Cross-domain URL
Step 1. Write a generic URL call function in server side.
Let’s use Django server as example:
In views.py

from django.views.decorators.gzip import gzip_page

#gzip the response content, this's not a must
@gzip_page
def get_crossdomain_data(request):
    try:
        url = request.GET['url']
        url = urllib.unquote(url).decode('utf8')
        jsonData = urllib2.urlopen(url).readlines()
        return HttpResponse(jsonData)
    except Exception,e:
        result={};
        result['success']= 'false'
        result['message']= str(e)
        return HttpResponse(result)

In urls.py, map the URL

(r'^get_crossdomain_data',views.get_crossdomain_data),

Step 2. Use the server URL to call Cross-domain URL
We need to encode the original URL and transfer it as an parameter to server, and then parse the response data

url = "http://alezeng.blogspot.com/api/report.dat";
url= "/get_crossdomain_data?url=" + encodeURIComponent(url);
$.get(url, function(str_data) {
    data = jQuery.parseJSON(str_data);
    //process data;
    process(data);
});

With all these approaches, you can choose the one works in your scenario.