1. What is REST?

REST stands for Representational State Transfer. (It is sometimes spelled "ReST".) It relies on a stateless, client-server, cacheable communications protocol -- and in virtually all cases, the HTTP protocol is used.

REST is an architecture style for designing networked applications. The idea is that, rather than using complex mechanisms such as CORBA, RPC or SOAP to connect between machines, simple HTTP is used to make calls between machines.

  • In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-based architecture.

RESTful applications use HTTP requests to post data (create and/or update), read data (e.g., make queries), and delete data. Thus, REST uses HTTP for all four CRUD (Create/Read/Update/Delete) operations.

REST is a lightweight alternative to mechanisms like RPC (Remote Procedure Calls) and Web Services (SOAP, WSDL, et al.). Later, we will see how much more simple REST is.

  • Despite being simple, REST is fully-featured; there's basically nothing you can do in Web Services that can't be done with a RESTful architecture.

REST is not a "standard". There will never be a W3C recommendataion for REST, for example. And while there are REST programming frameworks, working with REST is so simple that you can often "roll your own" with standard library features in languages like Perl, Java, or C#.

2. REST as Lightweight Web Services

As a programming approach, REST is a lightweight alternative to Web Services and RPC.

Much like Web Services, a REST service is:

  • Platform-independent (you don't care if the server is Unix, the client is a Mac, or anything else),
  • Language-independent (C# can talk to Java, etc.),
  • Standards-based (runs on top of HTTP), and
  • Can easily be used in the presence of firewalls.

Like Web Services, REST offers no built-in security features, encryption, session management, QoS guarantees, etc. But also as with Web Services, these can be added by building on top of HTTP:

  • For security, username/password tokens are often used.
  • For encryption, REST can be used on top of HTTPS (secure sockets).
  • ... etc.

One thing that is not part of a good REST design is cookies: The "ST" in "REST" stands for "State Transfer", and indeed, in a good REST design operations are self-contained, and each request carries with it (transfers) all the information (state) that the server needs in order to complete it.

3. How Simple is REST?

Let's take a simple web service as an example: querying a phonebook application for the details of a given user. All we have is the user's ID.

Using Web Services and SOAP, the request would look something like this:

<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:body pb="http://www.acme.com/phonebook">
  <pb:GetUserDetails>
   <pb:UserID>12345</pb:UserID>
  </pb:GetUserDetails>
 </soap:Body>
</soap:Envelope>

(The details are not important; this is just an example.) The entire shebang now has to be sent (using an HTTP POST request) to the server. The result is probably an XML file, but it will be embedded, as the "payload", inside a SOAP response envelope.

And with REST? The query will probably look like this:

http://www.acme.com/phonebook/UserDetails/12345

Note that this isn't the request body -- it's just a URL. This URL is sent to the server using a simpler GET request, and the HTTP reply is the raw result data -- not embedded inside anything, just the data you need in a way you can directly use.

  • It's easy to see why Web Services are often used with libraries that create the SOAP/HTTP request and send it over, and then parse the SOAP response.
  • With REST, a simple network connection is all you need. You can even test the API directly, using your browser.
  • Still, REST libraries (for simplifying things) do exist, and we will discuss some of these later.

Note how the URL's "method" part is not called "GetUserDetails", but simply "UserDetails". It is a common convention in REST design to use nouns rather than verbs to denote simple resources.

The letter analogy
A nice analogy for REST vs. SOAP is mailing a letter: with SOAP, you're using an envelope; with REST, it's a postcard. Postcards are easier to handle (by the receiver), waste less paper (i.e., consume less bandwidth), and have a short content. (Of course, REST requests aren't really limited in length, esp. if they use POST rather than GET.)

But don't carry the analogy too far: unlike letters-vs.-postcards, REST is every bit as secure as SOAP. In particular, REST can be carried over secure sockets (using the HTTPS protocol), and content can be encrypted using any mechanism you see fit. Without encryption, REST and SOAP are both insecure; with proper encryption in place, both are equally secure.

4. More Complex REST Requests

The previous section included a simple example for a REST request -- with a single parameter.

REST can easily handle more complex requests, including multiple parameters. In most cases, you'll just use HTTP GET parameters in the URL.

For example:

http://www.acme.com/phonebook/UserDetails?firstName=John&lastName=Doe

If you need to pass long parameters, or binary ones, you'd normally use HTTP POST requests, and include the parameters in the POST body.

As a rule, GET requests should be for read-only queries; they should not change the state of the server and its data. For creation, updating, and deleting data, use POST requests. (POST can also be used for read-only queries, as noted above, when complex parameters are required.)

  • In a way, this web page (like most others) can be viewed as offering services via a REST API; you use a GET request to read data, and a POST request to post a comment -- where more and longer parameters are required.

While REST services might use XML in their responses (as one way of organizing structured data), REST requests rarely use XML. As shown above, in most cases, request parameters are simple, and there is no need for the overhead of XML.

  • One advantage of using XML is type safety. However, in a stateless system like REST, you should always verify the validity of your input, XML or otherwise!

5. REST Server Responses

A server response in REST is often an XML file; for example,

<parts-list>
 <part id="3322">
  <name>ACME Boomerang</name>
  <desc>
   Used by Coyote in <i>Zoom at the Top</i>, 1962
  </desc>
  <price currency="usd" quantity="1">17.32</price>
  <uri>http://www.acme.com/parts/3322</uri>
 </part>
 <part id="783">
  <name>ACME Dehydrated Boulders</name>
  <desc>
   Used by Coyote in <i>Scrambled Aches</i>, 1957
  </desc>
  <price currency="usd" quantity="pack">19.95</price>
  <uri>http://www.acme.com/parts/783</uri>
 </part>
</parts-list>

However, other formats can also be used; unlike SOAP services, REST is not bound to XML in any way. Possible formats include CSV (comma-separated values) and JSON (JavaScript Object Notation).

Each format has its own advantages and disadvantages. XML is easy to expand (clients should ignore unfamiliar fields) and is type-safe; CSV is more compact; and JSON is trivial to parse in JavaScript clients (and easy to parse in other languages, too).

One option is not acceptable as a REST response format, except in very specific cases: HTML, or any other format which is meant for human consumption and is not easily processed by clients. The specific exception is, of course, when the REST service is documented to return a human-readable document; and when viewing the entire WWW as a RESTful application, we find that HTML is in fact the most common REST response format...

6. Real REST Examples

Here's a very partial list of service providers that use a REST API. Note that some of them also support a WSDL (Web Services) API, in addition, so you can pick which to use; but in most cases, when both alternatives are available, REST calls are easier to create, the results are easier to parse and use, and it's also less resource-heavy on your system.
So without further ado, some REST services:

  • The Google Glass API, known as "Mirror API", is a pure REST API. Here is an excellent video talk about this API. (The actual API discussion starts after 16 minutes or so.)
  • Twitter has a REST API (in fact, this was their original API and, so far as I can tell, it's still the main API used by Twitter application developers),
  • Flickr,
  • Amazon.com offer several REST services, e.g., for their S3 storage solution,
  • Atom is a RESTful alternative to RSS,
  • Tesla Model S uses an (undocumented) REST API between the car systems and its Android/iOS apps.

(This is far from an exhaustive list.)

7. AJAX and REST

AJAX is a popular web development technique that makes web pages interactive using JavaScript.

In AJAX, requests are sent to the server using XMLHttpRequest objects. The response is used by the JavaScript code to dynamically change the current page.

In many ways, AJAX applications follow the REST design principles. Each XMLHttpRequest can be viewed as a REST service request, sent using GET. And the response is often in JSON, a popular response format for REST. (See REST Server Responses, above.)

To make your AJAX application truly RESTful, follow the standard REST design principles (discussed later). You will find that most of them contribute to a good design, even if you don't think of your architecture in terms of REST.

A later section provides code samples for issuing HTTP requests in JavaScript, but if you've done any AJAX programming, you are already familiar with all that.

8. REST Architecture Components

Key components of a REST architecture:

  • Resources, which are identified by logical URLs. Both state and functionality are represented using resources.
    • The logical URLs imply that the resources are universally addressable by other parts of the system.
    • Resources are the key element of a true RESTful design, as opposed to "methods" or "services" used in RPC and SOAP Web Services, respectively. You do not issue a "getProductName" and then a "getProductPrice" RPC calls in REST; rather, you view the product data as a resource -- and this resource should contain all the required information (or links to it).
  • A web of resources, meaning that a single resource should not be overwhelmingly large and contain too fine-grained details. Whenever relevant, a resource should contain links to additional information -- just as in web pages.
  • The system has a client-server, but of course one component's server can be another component's client.
  • There is no connection state; interaction is stateless (although the servers and resources can of course be stateful). Each new request should carry all the information required to complete it, and must not rely on previous interactions with the same client.
  • Resources should be cachable whenever possible (with an expiration date/time). The protocol must allow the server to explicitly specify which resources may be cached, and for how long.
    • Since HTTP is universally used as the REST protocol, the HTTP cache-control headers are used for this purpose.
    • Clients must respect the server's cache specification for each resource.
  • Proxy servers can be used as part of the architecture, to improve performance and scalability. Any standard HTTP proxy can be used.

Note that your application can use REST services (as a client) without being a REST architecture by itself; e.g., a single-machine, non-REST program can access 3rd-party REST services.

9. REST Design Guidelines

Some soft guidelines for designing a REST architecture:

  1. Do not use "physical" URLs. A physical URL points at something physical -- e.g., an XML file: "http://www.acme.com/inventory/product003.xml". A logical URL does not imply a physical file: "http://www.acme.com/inventory/product/003".
    • Sure, even with the .xml extension, the content could be dynamically generated. But it should be "humanly visible" that the URL is logical and not physical.
  2. Queries should not return an overload of data. If needed, provide a paging mechanism. For example, a "product list" GET request should return the first n products (e.g., the first 10), with next/prev links.
  3. Even though the REST response can be anything, make sure it's well documented, and do not change the output format lightly (since it will break existing clients).
    • Remember, even if the output is human-readable, your clients aren't human users.
    • If the output is in XML, make sure you document it with a schema or a DTD.
  4. Rather than letting clients construct URLs for additional actions, include the actual URLs with REST responses. For example, a "product list" request could return an ID per product, and the specification says that you should use http://www.acme.com/product/PRODUCT_ID to get additional details. That's bad design. Rather, the response should include the actual URL with each item: http://www.acme.com/product/001263, etc.
    • Yes, this means that the output is larger. But it also means that you can easily direct clients to new URLs as needed, without requiring a change in client code.
  5. GET access requests should never cause a state change. Anything that changes the server state should be a POST request (or other HTTP verbs, such as DELETE).

10. ROA vs. SOA, REST vs. SOAP

ROA (REST Oriented Architecture) is just a fancy name for a SOA (Service Based Architecture) using REST services.

The main advantage of SOAP-based SOA over ROA is the more mature tool support; however, this could change over time. Another SOA advantages include the type-safety of XML requests (for responses, ROA can also use XML if the developers desire it).

The main advantage of ROA is ease of implementation, agility of the design, and the lightweight approach to things. In a way, SOA and SOAP is for people in business suits; that's what you'll find used in the banking and finance industries. Conversely, somebody that needs something up-and-running quickly, with good performance and low overhead, is often better off using REST and ROA.

For example, when explaining why they chose REST over SOAP, Yahoo! people write that they "believe REST has a lower barrier to entry, is easier to use than SOAP, and is entirely sufficient for [Yahoo's] services" (Yahoo! Developer Network FAQ, as of February 2008). This is true not only of REST vs. SOAP but also of ROA vs. SOA in general.

Another advantage of REST lies with performance: with better cache support, lightweight requests and responses, and easier response parsing, REST allows for nimbler clients and servers, and reduces network traffic, too.

As REST matures, expect it to become better understood and more popular even in more conservative industries.

A few words on hype vs. reality. In the comments below, I've linked to Pete Lacey's excellent criticism of SOAP, "The S Stands for Simple". And here's another one, by Alex Bell, published in Communications of the ACM (vol. 51, no. 10, October '08): "DOA with SOA".

11. Documenting REST Services: WSDL and WADL

WSDL, a W3C recommendation, is the Web Services Description Language. It is commonly used to spell out in detail the services offered by a SOAP server. While WSDL is flexible in service binding options (for example, services can be offered via SMTP mail servers), it did not originally support HTTP operations other than GET and POST. Since REST services often use other HTTP verbs, such as PUT and DELETE, WSDL was a poor choice for documenting REST services.

With version 2.0, WSDL supports all HTTP verbs and it is now considered to be an acceptable method of documenting REST services.

The second alternative is WADL, the Web Application Description Language. WADL is championed by Sun Microsystems. Like the rest of REST, WADL is lightweight, easier to understand and easier to write than WSDL. In some respects, it is not as flexible as WSDL (no binding to SMTP servers), but it is sufficient for any REST service and much less verbose.

Here is a fragment from a WADL specification, describing Amazon's "Item Search" service:

<method name="GET" id="ItemSearch">
 <request>
  <param name="Service" style="query"
   fixed="AWSECommerceService"/>
  <param name="Version" style="query" fixed="2005-07-26"/>
  <param name="Operation" style="query" fixed="ItemSearch"/>
  <param name="SubscriptionId" style="query"
   type="xsd:string" required="true"/>
  <param name="SearchIndex" style="query"
   type="aws:SearchIndexType" required="true">
    <option value="Books"/>
    <option value="DVD"/>
    <option value="Music"/>
  </param>
  <param name="Keywords" style="query"
   type="aws:KeywordList" required="true"/>
  <param name="ResponseGroup" style="query"
   type="aws:ResponseGroupType" repeating="true">
    <option value="Small"/>
    <option value="Medium"/>
    <option value="Large"/>
    <option value="Images"/>
  </param>
 </request>
 <response>
  <representation mediaType="text/xml"
   element="aws:ItemSearchResponse"/>
 </response>
</method>

As you can see, for format is mostly self-explanatory, and it enriches REST with such goodies as type safety using XML schema types.

Some REST advocates, however, find even the lightweight WADL to be an overkill. And indeed, most REST services are documented by no more than a textual description (a human-readable HTML file).

12. REST Examples in Different Languages

The following sections provide brief examples for accessing REST services in different programming languages. More than anything else, they present mechanisms for sending HTTP GET and/or POST requests in each language; the rest of using REST is simply a matter of architectural design.

You might wish to skip directly to your language of choice (the list is alphabetical):

Finally, the tutorial conclusion contains references to additional resources.

12.1. Using REST in C#

Issuing HTTP GET Requests
The key classes here are HttpWebRequest and HttpWebResponse from System.Net.

The following method issues a request and returns the entire response as one long string:

static string HttpGet(string url) {
  HttpWebRequest req = WebRequest.Create(url)
                       as HttpWebRequest;
  string result = null;
  using (HttpWebResponse resp = req.GetResponse()
                                as HttpWebResponse)
  {
    StreamReader reader =
        new StreamReader(resp.GetResponseStream());
    result = reader.ReadToEnd();
  }
  return result;
}

Remember that if the request URL includes parameters, they must be properly encoded (e.g., a space is %20, etc.). The System.Web namespace has a class called HttpUtility, with a static method called UrlEncode for just such encoding.

Issuing HTTP POST Requests
URL encoding is also required for POST requests -- in addition to form encoding, as shown in the following method:

static string HttpPost(string url, 
    string[] paramName, string[] paramVal)
{
  HttpWebRequest req = WebRequest.Create(new Uri(url)) 
                       as HttpWebRequest;
  req.Method = "POST";  
  req.ContentType = "application/x-www-form-urlencoded";

  // Build a string with all the params, properly encoded.
  // We assume that the arrays paramName and paramVal are
  // of equal length:
  StringBuilder paramz = new StringBuilder();
  for (int i = 0; i < paramName.Length; i++) {
    paramz.Append(paramName[i]);
    paramz.Append("=");
    paramz.Append(HttpUtility.UrlEncode(paramVal[i]));
    paramz.Append("&");
  }

  // Encode the parameters as form data:
  byte[] formData =
      UTF8Encoding.UTF8.GetBytes(paramz.ToString());
  req.ContentLength = formData.Length;

  // Send the request:
  using (Stream post = req.GetRequestStream())  
  {  
    post.Write(formData, 0, formData.Length);  
  }

  // Pick up the response:
  string result = null;
  using (HttpWebResponse resp = req.GetResponse()
                                as HttpWebResponse)  
  {  
    StreamReader reader = 
        new StreamReader(resp.GetResponseStream());
    result = reader.ReadToEnd();
  }

  return result;
}

For more examples, see this page on the Yahoo! Developers Network.

12.2. Using REST in Java

Issuing HTTP GET Requests
The key class here is HttpURLConnection, obtained by invoking openConnection on a URL object. Sadly, openConnection method's signature specifies that it returns the superclass type, URLConnection, and we have to downcast the result.

The following method issues a request and returns the entire response as one long string:

public static String httpGet(String urlStr) throws IOException {
  URL url = new URL(urlStr);
  HttpURLConnection conn =
      (HttpURLConnection) url.openConnection();

  if (conn.getResponseCode() != 200) {
    throw new IOException(conn.getResponseMessage());
  }

  // Buffer the result into a string
  BufferedReader rd = new BufferedReader(
      new InputStreamReader(conn.getInputStream()));
  StringBuilder sb = new StringBuilder();
  String line;
  while ((line = rd.readLine()) != null) {
    sb.append(line);
  }
  rd.close();

  conn.disconnect();
  return sb.toString();
}

(This code is very raw; it should be properly padded with try/catch/finally blocks to ensure the reader is closed, etc.)

Remember that if the request URL includes parameters, they must be properly encoded (e.g., a space is %20, etc.). The class URLEncoder can be used to perform this encoding.

Issuing HTTP POST Requests
URL encoding is also required for POST requests, as shown in the following method:

public static String httpPost(String urlStr, String[] paramName,
String[] paramVal) throws Exception {
  URL url = new URL(urlStr);
  HttpURLConnection conn =
      (HttpURLConnection) url.openConnection();
  conn.setRequestMethod("POST");
  conn.setDoOutput(true);
  conn.setDoInput(true);
  conn.setUseCaches(false);
  conn.setAllowUserInteraction(false);
  conn.setRequestProperty("Content-Type",
      "application/x-www-form-urlencoded");

  // Create the form content
  OutputStream out = conn.getOutputStream();
  Writer writer = new OutputStreamWriter(out, "UTF-8");
  for (int i = 0; i < paramName.length; i++) {
    writer.write(paramName[i]);
    writer.write("=");
    writer.write(URLEncoder.encode(paramVal[i], "UTF-8"));
    writer.write("&");
  }
  writer.close();
  out.close();

  if (conn.getResponseCode() != 200) {
    throw new IOException(conn.getResponseMessage());
  }

  // Buffer the result into a string
  BufferedReader rd = new BufferedReader(
      new InputStreamReader(conn.getInputStream()));
  StringBuilder sb = new StringBuilder();
  String line;
  while ((line = rd.readLine()) != null) {
    sb.append(line);
  }
  rd.close();

  conn.disconnect();
  return sb.toString();
}

As you can see, it's not a pretty sight (and that's before adding proper try/catch/finally structures). The problem is that, out of the box, Java's support for handling web connections is pretty low-level.

A good solution can be found in the popular Apache Commons library, and in particular the httpclient set of packages. See Yahoo! guide to REST with Java for details and examples. The documentation covers several interesting extras, such as caching.

12.3. Using REST in JavaScript

The page discusses sending REST requests from client-side (in-browser) JavaScript. If you're using server-side JavaScript, see your server vendor's documentation for creating HTTP requests.

If you have developed AJAX applications, all this will seem trivial to you: after all, every AJAX request is an HTTP request, and in many ways, AJAX applications are RESTful.

Creating XMLHttpRequest Objects
Sending HTTP requests in JavaScript involves the XMLHttpRequest object. Note that despite its name, neither the request nor the response has to involve XML.

Sadly, there is no standard way to create XMLHttpRequest objects. The following function is a cross-browser solution:

function createRequest() {
  var result = null;
  if (window.XMLHttpRequest) {
    // FireFox, Safari, etc.
    result = new XMLHttpRequest();
    if (typeof xmlhttp.overrideMimeType != 'undefined') {
      result.overrideMimeType('text/xml'); // Or anything else
    }
  }
  else if (window.ActiveXObject) {
    // MSIE
    result = new ActiveXObject("Microsoft.XMLHTTP");
  } 
  else {
    // No known mechanism -- consider aborting the application
  }
  return result;
}

Using XMLHttpRequest
An XMLHttpRequest object allows you to send a request, either GET or POST; however, it does not immediately return a value. Rather, you have to supply a callback function that will be invoked when the request completes. Confusingly, you callback is actually invoked several times (up to four times, depending on the browser), during different stages of the client/server interaction. It is only the fourth and final stage that interests us; the readyState field can be used to test for the stage, as shown in the following code fragment:

var req = createRequest(); // defined above
// Create the callback:
req.onreadystatechange = function() {
  if (req.readyState != 4) return; // Not there yet
  if (req.status != 200) {
    // Handle request failure here...
    return;
  }
  // Request successful, read the response
  var resp = req.responseText;
  // ... and use it as needed by your app.
}

Note that if the response is an XML response (denoted by the server using MIME type text/xml), it can also be read using the responseXML property. This property contains an XML document, and can be used as such using JavaScript's DOM navigation facilities.

Sending the Request
Once we have created the request object and set up its callback function, it is time to issue the request:

req.open("GET", url, true);
req.send();

For POST requests, use:

req.open("POST", url, true);
req.setRequestHeader("Content-Type",
                     "application/x-www-form-urlencoded");
req.send(form-encoded request body);

For more information about sending HTTP requests from JavaScript, just google for XMLHttpRequest.

12.4. Using REST in Perl

To work with HTTP in Perl, we will use LWP -- the Library for WWW in Perl.

Issuing GET Requests
GET requests are pretty trivial with LWP, especially if you don't care much about setting headers in the request or reading headers in the response:

use LWP::Simple;

my $url = 'http://www.acme.com/products/3322';
          # ACME boomerang
my $response = get $url;
die 'Error getting $url' unless defined $response;

For more advanced features, you'll need to create a browser object, thus:

use LWP;
my $browser = LWP::UserAgent->new;
my $url = 'http://www.acme.com/products/3322';

# Issue request, with an HTTP header
my $response = $browser->get($url,
  'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 7.0)',
);
die 'Error getting $url' unless $response->is_success;
print 'Content type is ', $response->content_type;
print 'Content is:';
print $response->content;

Issuing POST Requests
The same browser object defined above can be used to issue POST requests, too. Field names are directly mapped to values, thus:

my $response = $browser->post($url,
  [
   'firstName' => 'John',
   'lastName' => 'Doe'
  ],
);
die 'Error getting $url' unless $response->is_success;

Note that the UserAgent class allows you to easily set and read cookies, too, but these should be avoided in REST designs.

Additional information about using LWP for web requests can be found in the article Web Basics with LWP, by Sean M. Burke, author of Perl & LWP.

12.5. Using REST in PHP

Issuing GET Requests
Modern versions of PHP make it trivial to GET web pages: any file-access function (even include!) works seamlessly with URLs, too. Thus, you can use fopen, file_get_contents, and any other file-reading function to issue GET requests. For example:

$url = "http://www.acme.com/products/3322";
$response = file_get_contents($url);
echo $response;

Any parameters passed to GET requests must be encoded (e.g., a space is %20); you can encode strings using the urlencode function.

Issuing POST Requests
In stark contrast to the ease of doing a GET, there's no simple way to do a POST in PHP. You have to open a connection to the server and manually send all HTTP headers. Here's a simple function that will do the trick, for any HTTP method:

function httpRequest($host, $port, $method, $path, $params) {
  // Params are a map from names to values
  $paramStr = "";
  foreach ($params as $name, $val) {
    $paramStr .= $name . "=";
    $paramStr .= urlencode($val);
    $paramStr .= "&";
  }

  // Assign defaults to $method and $port, if needed
  if (empty($method)) {
    $method = 'GET';
  }
  $method = strtoupper($method);
  if (empty($port)) {
    $port = 80; // Default HTTP port
  }

  // Create the connection
  $sock = fsockopen($host, $port);
  if ($method == "GET") {
    $path .= "?" . $paramStr;
  }
  fputs($sock, "$method $path HTTP/1.1\r\n");
  fputs($sock, "Host: $host\r\n");
  fputs($sock, "Content-type: " .
               "application/x-www-form-urlencoded\r\n");
  if ($method == "POST") {
    fputs($sock, "Content-length: " . 
                 strlen($paramStr) . "\r\n");
  }
  fputs($sock, "Connection: close\r\n\r\n");
  if ($method == "POST") {
    fputs($sock, $paramStr);
  }

  // Buffer the result
  $result = "";
  while (!feof($sock)) {
    $result .= fgets($sock,1024);
  }

  fclose($sock);
  return $result;
}

Issuing a POST request using this function is as simple as:

$resp = httpRequest("www.acme.com",
    80, "POST", "/userDetails",
    array("firstName" => "John", "lastName" => "Doe"));

One alternative to this approach is using PHP's CURL support; however, I'm not sure if it's really easier.

12.6. Using REST in Python

Issuing GET Requests
The Python module urllib2 makes reading URLs trivial:

import urllib2

url = 'http://www.acme.com/products/3322'
response = urllib2.urlopen(url).read()

Errors are reported as exceptions (urllib2.HTTPError or urllib2.URLError).

Issuing POST Requests
A POST request is just as easy, simply passing (encoded) request data as an extra parameter to urlopen, thus:

import urllib
import urllib2

url = 'http://www.acme.com/users/details'
params = urllib.urlencode({
  'firstName': 'John',
  'lastName': 'Doe'
})
response = urllib2.urlopen(url, params).read()

Note that encoding is done using a function from the urllib module.

12.7. Using REST in Ruby

As with Python, sending HTTP requests in Ruby is extremely easy.

Issuing GET Requests
We use the class Net::HTTP to do all the magic:

require 'net/http'

url = 'http://www.acme.com/products/3322' # ACME boomerang
resp = Net::HTTP.get_response(URI.parse(url))

resp_text = resp.body

The response field code contains the HTTP response code. To make things simpler, the result object's very class indicates the response type; for example, resp (in the example above) will be of type Net::HTTPSuccess if the response is 2xx (HTTP OK code), or Net::HTTPNotFound for 404 responoses (HTTP Not Found code). A complete hierarchy of the response classes appears in Net::HTTP's documentation.

Issuing POST Requests
We need Net::HTTP's post_form method for POSTing:

require 'net/http'

url = 'http://www.acme.com/user/details'
params = {
  firstName => 'John',
  lastName => 'Doe'
}

resp = Net::HTTP.post_form(url, params)

resp_text = resp.body

The form encoding is application/x-www-form-urlencoded by default.

12.8. Using REST in Groovy

Groovy, a dynamic language for the JVM, has built-in support for REST. The RESTClient class is an extension of HTTPBuilder, designed specifically for making REST calls easier (for example, by having convenience methods for GET, POST, etc.).

Issuing GET Requests
Given RESTClient, it's pretty easy:

import groovyx.net.http.RESTClient
 
def client = new RESTClient( 'http://www.acme.com/' )
def resp = client.get( path : 'products/3322' ) // ACME boomerang

assert resp.status == 200  // HTTP response code; 404 means not found, etc.
println resp.getData()

The response field data is the parsed response content, always buffered in-memory.

Issuing POST Requests
Equally simple, using the same class:

import groovyx.net.http.RESTClient
 
def client = new RESTClient( 'http://www.acme.com/' )
def resp = client.post( path : '/user/details',
                        body : [ firstName:'John', lastName:'Doe' ] )

assert resp.status == 200

Here, too, the response is available in resp.getData().

13. For More About REST

14. Questions and Answers

In this section, I'll be adding common questions about REST, or real issues I've encountered while developing RESTful services.

If you have a question, feel free to post it as a comment on this page, or on any other relevant page in this tutorial.

Questions posted so far:

  1. How do I perform atomic operations using REST?
  2. How do I delete items using a REST API?
  3. How do I handle authentication in REST?
  4. How do I send complex objects as parameters?

14.1. How do I perform atomic operations using REST?

QUESTION: How do I perform atomic operations using REST? If I would like to execute multiple operations, but have them all appear as an single, atomic transaction, REST seems inappropriate.

ANSWER: REST faces the exact same problem as SOAP-based web services with regards to atomic transactions. There is no stateful connection, and every operation is immediately committed; performing a series of operations means other clients can see interim states.

Unless, of course, you take care of this by design. First, ask yourself: do I have a standard set of atomic operations? This is commonly the case. For example, for a banking operation, removing a sum from one account and adding the same sum to a different account is often a required atomic operation. But rather than exporting just the primitive building blocks, the REST API should provide a single "transfer" operation, which encapsulates the entire process. This provides the desired atomicity, while also making client code much simpler. This appracoh is known as low granularity services, or high-level batch operations.

If there is no simple, pre-defined set of desired atomic operation sequences, the problem is more severe. A common solution is the batch command pattern. Define one REST method to demarcate the beginning of a transaction, and another to demarcate its end (a 'commit' request). Anything sent between these sets of operations is queued by the server but not committed, until the commit request is sent.

This pattern complicates the server significantly -- it must maintain a state per client. Normally, the first operation ('begin transaction') returns a transaction ID (TID), and all subsequent operations, up to and including the commit, must include this TID as a parameter.

It is a good idea to enforce a timeout on transactions: if too much time has passed since the initial 'begin transaction' request, or since the last step, the server has the right to abort the transaction. This prevents a potential DoS attack that causes the server to waste resources by keeping too many transactions open. The client design must keep in mind that each operation must be checked for a timeout response.

It is also a good idea to allow the client to abort a transaction, by providing a 'rollback' API.

The usual care required in designing code that uses multiple concurrent transactions applies as usual in this complex design scenario. If at all possible, try to limit the use of transactions, and support high-level batch operations instead.

14.2. How do I delete items using a REST API?

QUESTION: How do I provide a REST API for deleting resources in the system (e.g., a record from a database)? I was told that using a simple GET API, or even POST, is inappropriate, but I don't know why.

ANSWER: There's a well-known story about a company that had its entire database wiped out by Google. Why? Because they had a "delete" link on every web page, and Googlebot crawled all links it could find...

The lesson was quickly learned by the entire industry: do not expose deletion link, or more generally, state-changing links, as simple web links. And since a REST API is often described as a simple web URL, the convention was carried over.

In fact, if you never expose your REST action URLs as web links, you could use standard GET operations for deletion. However, it's not a good idea. On a conceptual level, a good REST design takes advantage of the various HTTP verbs, to prevent errors, confusion, or mistaken operations. And there's a very specific HTTP verb for deletion, namely DELETE.

See also item #5 in the page about REST Design Guidelines in this tutorial.

14.3. How do I handle authentication in REST?

QUESTION: Most services require user to login before exploring further. If cookies are not recommended in REST, does it mean I have to go thru authentication on every single request (e.g., HTTP AUTH)?

ANSWER: There are two basic approaches here. The first is, use HTTP AUTH. The (human) user will be prompted for the credential just once (or they will be loaded from file, depending on the system at hand). The client software will compute the Base64 encoding of the credentials and will include them in each future HTTP request to the server (using the "Authorization" HTTP header).

The second alternative is to create a dedicated login service, that accepts credentials and returns a token. This token should then be included, as a URL argument, to each following request (e.g., by addding "&authtoken=XYZ" to the URL). Of course, the API (including the argument's name) should be clearly defined.

Each approach has its benefits, and its limitations. The first approach is easy to test using browsers. Just connect to the service with your browser, and on the first visit, you'll get a the username/password prompt. The browser than caches your credentials and automatically sends them on all following requests (just like the REST client software would have done!). The main advantage of the second approach is that tokens can be created with an expiration date (managed on the server, unlike cookie expiration). For some services, this is important.

And what about cookies? As I said elsewhere, these violate the "state transfer" notion of REST, where the complete state should be passed with each request. While cookies can be limited to function just like the Authorization header, why do that when you have a dedicated, special-purpose header?

14.4. How do I send complex objects as parameters?

QUESTION: The REST client is sending complex objects as a list of standalone parameters: for example, firstName, lastName, birthDate, etc. The backend, which I'm developing, has to turn these into high-level-language objects, such as User. How do I convert these arguments into objects?
ANSWER: The most straightforward way to do this would be a constructor to the complex object class (here, User) which accepts a map of key/value pairs; these would be the fine-grained parameters passed by the client. For example, in Java, class User could have a constructor with a single argument, of type Map<String,String>.
Now, how do we convert the map into a new object? In languages with good reflection mechanisms, such as Java or C#, it might be tempting to use reflection here: go over the map keys, for each map key try to find a data member in the class, and set that data member to the value mapped to this key. For example, if the first key in the map is firstName, a call to getField on the Class object representing this would provide you with a field object that can be used to set the actual field. A simple loop for setting all fields, and you're done!
I strongly advise against this approach. It could present a security risk (for example, you end up setting a private field. Do you really want to re-implement the language's security mechanisms?). It also circumvents any setters that might be defined for these fields, and which are used to enforce any class invariants. It is also probably not very efficient, though this is less of a consideration.
Instead, write simple, possibly "boring" code: for each field you'd like to set, find if a matching key exists in the map (note that the map key and the field name don't have to be identical now; the field could be firstName while the REST parameter was first_name). If found, pass the matching value from the map to the field's setter method.
Avoid validity checks in this constructor. If your code insists that first-name should be at least two letters long, this should be verified in the setFirstName method (or property setter, in C#). The most validity-checks that should appear in this constructor is in converting string values to non-string ones, for example for setting integer fields.