Home     Publications     Articles and Projects     PhD Thesis     Links    


Web Services with AJAX and PHP

Web Services are very useful for modularising large systems and making the data and functions of those modules available to one another. They enable integration and reuse of existing or legacy systems and systems written in different programming languages or in different runtime environments. They also enable companies that provide complex services to deliver an API to customers while retaining control of their software. The company can then improve the software over time without having to release updated code to the customer. Often the services provided use large databases or have large hardware requirements, so it is much simpler that they host the software rather than the customer.

I have implemented my own client and server stubs for web services in PHP. I know there are standard libraries for this, but it was almost as easy to just write them from scratch. In PHP, the client just encodes and marshals parameters into a URL and uses cURL to obtain a result XML string from a specified server location.

In Javascript, there is a client stub as well, but instead of cURL, we can use the browser’s built-in XMLHttpRequest object for getting a URL:

 
function ajax_request(url) {
	
     if (window.XMLHttpRequest) {              
          AJAX=new XMLHttpRequest();              
     }
     else {                                  
          AJAX=new ActiveXObject("Microsoft.XMLHTTP");
     }
	
     if (AJAX) {
          AJAX.open("GET", url, false);                             
          AJAX.send(null);
          return AJAX.responseText;                                         
     } 
     else {
          return false;
     }                                             
	
}

The server has some validation of the parameters before calling a local handler to deal with the requested service.

For web services, parameters need to be formatted in a standard language, so that different platforms can talk to one another. I’m using XML for this. Formatting data in XML is quite easy. For example, a set of rectangles might look like:

 
<?xml version="1.0"?>
	<rectangles>
		<rectangle>
			<length>
				5
			</length>
			<width>
				7
			</width>
		</rectangle>
		<rectangle>
			<length>
				3
			</length>
			<width>
				1
			</width>
		</rectangle>
	</rectangles>

To decode this data is a bit harder, but in both PHP and Javascript there are libraries available for this. In PHP, there is the SimpleXMLElement XML parser. The parser converts the XML into a parse tree formatted as a PHP data structure. It is easy then to pick the required node using PHP operators. To get the first rectangle width:

 
     $result_xml = web_service_client(array("get_rectangles", 2), "rectangle_server");
     $result = new SimpleXMLElement($result_xml);
     $first_rectangle_width = $result->rectangle[0].width;

In Javascript, I use the jQuery library, which has things called selectors which are normally used for picking elements and groups of elements from HTML documents for DHTML purposes. They work just as well for XML:

 
     first_rectangle_width = $(result_xml).find("rectangle:nth-child(1) width").text();

One variation of this implementation is to use a cache for any services that just read information. The cache is refreshed every half an hour, and our websites load fast because there’s almost no delay waiting for a web service to respond.

Web Services are often available on public webservers, so they might need to be secured. First, we always use SSL ( https ) to prevent eavesdropping and to authenticate the server. To prevent unauthorised access to the server, each client is given a key. Each request URL is appended with the key and the result hashed. The server verifies the hash using another copy of the key.

One problem with Javascript is that you may only call web services that are at the same host as your webpage. This is to prevent cross-site scripting attacks whereby injected Javascript code might load an attack payload from a server outside your system, or send out some private information from a form. To get around this, I use a set of PHP stubs on the local web server, which the Javascript client calls. Each stub then simply makes a call to the web service via the PHP client.