J1.5

Avoiding web browser same origin policy in Ajax applications

From Joomla! Documentation

Revision as of 18:39, 5 November 2011 by Nicholasjohn16 (talk | contribs)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

The "J1.5" namespace is an archived namespace. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.

If you need to access a web service, using Ajax, that is running on a server that is not in your domain, then you will run up against the "same origin policy" [1] that will prevent you from retrieving data from outside your own domain for security reasons. There needs to be some way to circumvent this restriction on those occasions where the web service is trusted.

The most common method of circumventing the same origin policy in Ajax implementations is to access the remote web service via a proxy running in your domain. The proxy uses an HTTP client library (such as [2]) to access the remote server. This technique is usually simple enough, but can get tougher if the remote server requires authentication or uses cookies to track state between requests. On the plus side, using a proxy generally makes it easier to cache Ajax responses; something that is normally quite difficult.

To add a simple proxy to your Joomla component you simply need to add an extra task to the controller. The following code shows roughly what it might look like, given a static HTTP client class called httpClient with a method that will request a page from a remote server.

<?php
/**
 * Support cross-domain Ajax request by using the component as a proxy.
 * To use this facility replace "option" with "type" and "task" with "request"
 * in the query that would otherwise be sent to the remote server.
 */
function proxy()
{
	$uri = & JFactory::getURI();
	$query = $uri->getQuery( true );
	$query['option'] = $query['type'];
	unset( $query['type']);
	unset( $query['task']);
	if (isset( $query['request'] )) {
		$query['task'] = $query['request'];
		unset( $query['request']);
	}

	// Make the API call.
	$response = httpClient::call( $query );
	if ($response->status != '200') {
		JError::raiseError( 500, JText::_( 'Remote server error' ) );
		return false;
	}

	// And return the response.
	echo $response->data;
	jexit();
}

This example also shows how to work around the situation where the remote server is also running Joomla, in which case it will require a URL containing option and task arguments that may not match those required by the proxy. For example, suppose you want to make an Ajax request to a remote server using this URL:

http://www.remoteserver.com/index.php?option=com_remotecomponent&task=remotetask&arg=something

To avoid the same origin policy you send the request to the proxy instead using this URL:

http://www.localserver.com/index.php
     ?option=com_localcomponent
     &task=proxy&type=com_remotecomponent
     &request=remotetask
     &arg=something

You will need to adapt this code to meet your particular requirements, such as if you need to specify the controller in order to reach the proxy.

Adding cookie and cache support is left as an exercise for the reader.