
API, HTTP, Microcontent, REST, RPC, Share, SOAP, Platform
In a financial forecasting app, Tracy runs an algorithm to forecast the next four interest rates. The browser script uploads the parameters to an "Interest Rate Forcaster" Web Service, which eventually outputs a concise list of future rates, free of any HTML markup: 4.5, 3.4, 4.0, 4.1.
Ajax Apps can access the server directly and require well-scoped services instead of the conventional-style scripts that output an entire HTML page.
Many organisations like to expose their functionality and data for third-parties to access. The API needs to be clean and easy to use.
Expose server-side functionality as fine-grained, easy-to-use, Web Services. "Web Service" is an overloaded term, and the Ajax Patterns use a fairly broad definition:
Under this definition, there is considerable flexibility involved in creating a Web Service:
Deciding on all these things is the main task involved in creating a Web Service.
Web Services are the latest in a long tradition of distributed computing, with technologies like SunRPC, CORBA and EJB along the way. They've arisen quite separately from Ajax, as a general-purpose way to expose services to interested clients. These clients are usually standalone processes with no user-interface as well as desktop clients and web server scripts. Until recently, they were irrelevant to anything inside a web browser, which could only communicate with services capable of returning an entire HTML page. But thanks to remoting technologies, Javascript can now make use of such services. Indeed, a clean Web Service is actually the best thing for a remoting technologies to be calling - it makes the call easier and having a fine-grained response is good for the response handler. Thus, there's a strong synergy between Ajax and Web Services.
Here's the PHP code for a one-liner web service to perform a sum (imaginative, I know):
<?
echo $_GET["figure1"] + $_GET["figure2"];
?>
You can try the service by entering
http://ajaxify.com/run/xmlHttpRequestCall/sumGet.phtml?figure1=5&figure2=10
in your browser's address bar. The entire response will be "15". As the
example shows, a web service's response can be as simple as a single
value. Other times, it might be some HTML, but even then, it will
usually only be a snippet rather than an entire page. For example, the
above service could be refactored to show the result as a heading.
<?
echo "<h1>" . ($_GET["figure1"] + $_GET["figure2"]) . "</h1>";
?>
A collection of related services like these forms an HTTP-based API that exposes server functionality. Most Ajax apps will access the API from the browser via the “XMLHttpRequest Call” and alternative remoting techniques. In addition, third-parties can access Web Services and use them for their own applications, web or not.
This pattern only introduces the concept of Web Services. There are a number of decisions you need to make when designing such services for your own application. Will the service output XML to be processed in the browser, HTML to be displayed directly, or some other format? How will the URLs look? What sort of input will it take? All these issues are discussed in the ??? chapter.
The single most important decision about a web service, as with any form of API, is to know how it will be used. In particular, will it be available for third-parties as a generic interface to your system, or are you developing it purely for an Ajax browser app to access. If the latter, then you might want to practice feature-driven development and let the browser app drive web service design - see “Simulation Service”
If there are third-parties involved, it becomes a balancing act between their needs and the needs of your browser app. Since they will probably be accessing your server from more powerful environments than the average web browser, you might need to add some redundancy to support each type of client. The API for third-parties might be more general, whereas the browser sometimes needs an API that knows something about the application. In an extreme case, it tracks application state and outputs the actual HTML to be shown to the user.
Web services are seen as having a kind of synergy with Ajax, as Ajax Apps can talk to the same interface already being offered to third-party clients. However, sometimes you want the web service to be restricted to third parties. That's going to be difficult on the public web, since pretty much anything a browser can access will also be available to third-party clients. So, you might have spent ages designing a nice, clean, web service to make browser scripting as painless as possible, only to discover that third parties are reaping the benefits. There's no magic bullet here, but here are a few suggestions:
Require users to be logged in, with an authenticated email address, in order for the application to make use of web services. You can then use cookies or upload unique session IDs to authenticate the user.
Consider using a system like Captcha (TODO link), where the user is forced to perform a challenge that should be about impossible for an automated script to perform. You might require a challenge be solved once an hour, say.
Use standard filtering techniques, like blocking certain IP addresses and refusing requests if they arrive too frequently.
Use obfuscation and encryption. This idea is based on a tricky little anti-spam plugin for Wordpress, TODO. By outputting a customised piece of obfuscated Javascript that's used to decrypt web service content, you force any client programmer to do two things: first, hook into a Javascript engine in order to execute the code; second, consume resources performing the decryption. Neither are impossible, but they do make the task less appealing. Unfortunately, they also break the clean nature of web services, though you should be able to abstract the messy details with a suitable Javascript API.
Just about any Ajax App has some kind of web service. In these examples, we'll look at a public API designed for third-party usage, then at a couple of services only accessed from a corresponding Ajax browser script.
Technorati exposes its search capability for third-party use. To perform a query, you run an HTTP GET on the following URL: http://api.technorati.com/search?key=1234&query=serendipity, where 1234 is your personal technorati key and serendipity is the search query. What you'll get back is an XML document listing the results.
Netvibes is an Ajax portal which gets it content from several Web Services. To get weather data, the browser invokes a service like this:
http://netvibes.com/xmlProxy.php?url=http%3A//xoap.weather.com/weather/local/USNY0996%3Fcc%3D*%26unit%3Dd%26dayf%3D4
The service is actually a proxy because it passes through to a real weather service at weather.com. As the URL shows, you can specify parameters such as location (USDNYC0996), units (d), number of days ahead (4). The output is an XML document without any HTML markup.
<weather ver="2.0">
<head>
<locale>en_US</locale>
<form>MEDIUM</form>
...
</head>
<dayf>
...
<hi>N/A</hi>
<low>46</low>
<sunr>7:18 AM</sunr>
<suns>4:34 PM</suns>
...
</dayf>
...
</weather>
Alexander Kirk's Wish-O-Matic provides Amazon recommendations. The browser posts the following information to a service at http://alexander.kirk.at/wish-o-matic/search=grand&catalog=Books&page=1&locale=US&_=:
search=grand&catalog=Books&page=1&locale=US&_=
The service then responds with a list of books. Unlike the previous service, the data is pure HTML, ready for immediate display in the browser.
<table><tr><td style="width: 500px">
<b>Author:</b> Kevin Roderick<br/><b>Title:</b> Wilshire Boulevard:
The
Grand Concourse of Los Angeles<br/><b>ISBN:</b> 1883318556<br/><a
href="javascript:void(add_item('1883318556', 'Wilshire Boulevard: The Grand
Concourse of Los Angeles',
'http://images.amazon.com/images/P/1883318556.01._SCTHUMBZZZ_.jpg'))">My
friend likes this item!</a></td>
...
</td></tr>
</table>
<br/>
<a href="javascript:void(prev_page())">< prev</a> |
<a href="javascript:void(next_page())">next ></a>
AjaxCaller is a Javascript HTTP client used in examples throughout this book, explained in the Code Example for “XMLHttpRequest Call”. Here, we'll look at a web service used in the testAjaxCaller application, a very simple service that just echoes its input.
httpLogger begins by outputting request method (e.g. "GET" or "POST"), its own request URL, and CGI variables present in the URL and body.
echo "<p>Request Method: $requestMethod</p>";
echo "<p>Request URL: ".$_SERVER['REQUEST_URI']."</p>";
echo "<p>Vars in URL: ".print_r($_GET, TRUE)."</p>";
echo "<p>Vars in Body: ".print_r($_POST, TRUE)."</p>";
A separate function is used to read the body, which can also be outputted with a regular print or echo statement.
function readBody() {
$body="";
$putdata = fopen("php://input", "r");
while ($block = fread($putdata, 1024)) {
$body = $body.$block;
}
fclose($putdata);
return $body;
}
All the patterns in ??? explain various strategies for designing Web Services with clean, maintainable, interfaces.
The main point of this pattern is to guide on designing your own Web Services. However, there are times when your server script will need to call on an external web service, as explained in “Cross-Domain Proxy”.
A “Simulation Service” is a "dummy" service that produces canned responses, a useful device while developing the browser-side of an Ajax App.
The nice thing about Web Services, compared to most aspects of web development, is that it's easy to write automated tests, as described in “Service Test”.