Technology

Cross-domain Ajax, part 1: Using JSON-P

Posted by Pixafy Team

Asynchronous HTTP requests have given web pages the ability to be more dynamic and interactive.

AJAX provides developers with the ability to perform an HTTP requests behind the scenes. However, for security reasons modern web clients maintain the same-origin policy.  Unfortunately, this policy will only allow XMLHTTPRequests from the same domain name as the origin.

One popular work around is to exploit the open policy for the ‘<script>’ element.  This method uses JSONP (JSON with padding) by inserting code into a script tag on the referring page.

Essentially, JSONP is a JSON object wrapped in a function call.  The JSON data is passed into the function as a parameter.  Here is a simple example of a JSONP to illustrate the concept:

myfunction(   {
       name:harry,
       city: anytown,
       phone: 555-555-1212
} )

In this example, we are processing a form using a server side script in PHP.  When the submit button is clicked, a script tag is inserted to the head element on the calling page.  This script tag will load a PHP server side script from a different domain.  This script will return a JSONP object.

The code

index.php – calling script on test.com

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<title>Cross Domain Ajax with JSONP Example</title>
		<meta http-equiv="content-type"  content="text/html;charset=utf-8" />

		<script type="text/javascript">
		<![CDATA[
function lookup( form ) {

	var insertScript = document.createElement('script');

	insertScript.setAttribute('src', form.action + '&id=' + form.elements[0].value);

	// add our script to the head of our document
	document.getElementsByTagName('head')[0].appendChild(insertScript);

	return false;
}

function process ( data ) {

	var resultDiv = document.getElementById('results');

	resultDiv.innerHTML = 'id: ' + data.id + '<br />'
		+ 'data1: ' + data.data1 + '<br />'
		+ 'data2: ' + data.data2 + '<br />';
}

]]>
</script>

	</head>

	<body>
		<!-- Notice here we are calling to a different domain name -->
		<form action="http://test2.com/processScript.php?callback=process" method="get">

			Enter id to lookup:
			<input type="text" name="id" id="id" />

			<input type="submit" onclick="lookup(this.form); return false;"/>

		</form>

		<div id="results">

		</div>

	</body>

</html>

processScript.php – Server Side PHP script on located on test2.com

<?php

function get_from_db($id) {

	// dummy database lookup

	return array(
		'id'			=>	$id,
		'data1'		=>	'SomeData1',
		'data2'		=>	'SomeMoreData2'
	);

}
	// be sure to set the content type to avoid browser warnings
	header('Content-type: application/json');

	$callback	=	$_GET['callback'];
	$id		=	$_GET['id'];

	// lookup some stuff in db ...
	$data	=	get_from_db($id); 

	// return json padded with callback function
	echo $callback .'('. json_encode($data) .');';

This example is using pure javascript.  jQuery implements this using either $.getJSON() or $.ajax() with special parameters. See the jQuery documentation for details on how to initiate an asynchronous call with JSONP using jQuery: http://api.jquery.com/jQuery.getJSON/ and http://api.jquery.com/jQuery.ajax/ under the Datatypes heading.

Part 2, focusing on cross-origin resource sharing, will be posted to the blog soon!

Questions or comments? Share them below, or tweet us @Pixafy!

Tags