How to add JSONP support to a web service

I needed to do this yesterday, so that a developer could work on a project on his own machine while accessing some REST services I developed on an intranet server. Cross-domain requests are prohibited by the same origin policy security that govern client-side Javascript programs. JSONP gets around this by sending back a Javascript function which encloses the JSON data, rather than just the JSON data. This is known as a callback and is used like this:

$.getJSON("http://www.thing.com/services/webservice_json?callback=?", 
         { "param" : "abc" },
         function(json) { 
             alert("Fetched " + json.field1 + ", " + json.field2); 
         });

So I needed to modify the web services to handle this. Turns out this was really easy:

use CGI; 
use JSON; 
my $c = CGI->new; 

# Get the callback function name 
my $callback = $c->param('callback');i

if ($callback) { 
    print 'Access-Control-Allow-Origin: *';
    print 'Access-Control-Allow-Methods: GET'; 
    print "Content-type: application/javascript\n\n";
} else { 
    # Header for access via browser, curl, etc. 
    print "Content-type: application/json\n\n"; 
} 

# Fake up some sample data 
my %json; 
$json{'IP'} = $ENV{REMOTE_ADDR}; 
$json{'useragent'} = $ENV{HTTP_USER_AGENT}; 
$json{'list'} = [ 'a', 'b', 'c', 'd', 'e' ]; 

# Convert %json to a scalar containing a JSON formatted string
my $json = to_json(\%json, {pretty=>'1'}); 

if ($callback) { 
    print $callback . '(' . $json . ');'; 
} else { 
    print $json,"\n"; 
}

Leave a comment

About sue spence (virtualsue)

user-pic Polyglot developer, though deep down I think of myself as a C programmer.