RESTful Web Services for Resource-Oriented Architectures (ROA) – Part 3 – The Uniform Interface

“The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.”1 For a web service we use the HTTP protocol. And to create a RESTful a web service, we must use HTTP’s interface uniformly, i.e. the same way every service across the web uses HTTP as specified in the HTTP 1.1 standard.2 There can be no “changes to the communication protocols aside from filling-out or fixing the details of underspecified bits of standard protocols, such as HTTP’s PATCH method or Link header field.”3

In my previous posts on RESTful web services, we discussed the resource URIs and HATEOAS. Now we’ll consider how our service follows the Uniform Interface as provided by HTTP.

Our Jazz Web Service uses the standard HTTP verbs GET, PUT, POST and DELETE as defined by RFC 2616. A GET request is always safe and results in a representation of an existing resource being sent to the requester. PUT and DELETE are idempotent – meaning that regardless of the number of times an identical request is made, the result is the same. For example, if you send a DELETE request to jazz/artists/123 and then send it again jazz/artists/123 is still gone. Similarly, PUT is used to edit an existing resource. If you PUT identical information to an existing URI the outcome is the same as when you PUT the same data the first time. POST, on the other hand, is neither safe nor idempotent but is used to append a “new subordinate of the resource identified by the Request-URI”.4 Posting identical information will result in duplicate resources with multiple URIs.

Additionally, each verb’s action is identical – i.e. uniform – across all service URIs that accept the verb. A GET to any service URI results in the safe return of a resource representation. All URIs that accept a PUT do so to edit the resource by modifying the representation and putting it back to URI. Any URI that accepts a DELETE will be removed from the service whenever a delete command is sent to the URI. A POST is only accepted by the bookmark URI and results in new artists being appended to the resource.

We must also include standard HTTP response codes and headers. The Jazz Web Service response headers include a response code and text, a list of the allowed HTTP verbs for the URI, the response content type and the location. For example, if the resource still exists, a GET to http://dlwelchservices.com/jazz/artists/2 results in:

200 OK
Allow: GET, PUT, DELETE
Content-Type: application/xml; charset=utf-8
Location: http://dlwelchservices.com/jazz/artists/2
...
<?xml version="1.0" encoding="utf-8"?>
<JazzArtist xmlns="http://schemas.dlwelch.com/JazzService" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Artist>
  <FirstName>Ella</FirstName>
  <LastName>Fitzgerald</LastName>
  <Grammys>14</Grammys>
  <link rel="self" href="http://dlwelchservices.com/jazz/artists/2" type="application/xml"/>
 </Artist>
 <Links>
  <link rel="edit" href="http://dlwelchservices.com/jazz/artists/2" type="application/xml"/>
  <link rel="delete" href="http://dlwelchservices.com/jazz/artists/2" type="application/xml"/>
  <link rel="/jazz/rel/home" href="http://dlwelchservices.com/jazz/artists" type="application/xml"/>
 </Links>
</JazzArtist>

And a POST to the bookmark URI will result in a 201 Created code along with the new representation of the Jazz Artists root listing that contains the newly appended artists:

201 Created
Allow: GET,POST
Content-Type: application/xml; charset=utf-8
Location: http://dlwelchservices.com/jazz/artists
...
<?xml version="1.0" encoding="utf-8"?>
<JazzArtists xmlns="http://schemas.dlwelch.com/JazzService" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Artists>
<Artist>
<FirstName>Nina</FirstName>
<LastName>Simone</LastName>
<Grammys>0</Grammys>
<link rel="self" href="http://dlwelchservices.com/jazz/artists/1" type="application/xml"/>
</Artist>
...
<Artist>
<FirstName>New</FirstName>
<LastName>Artist</LastName>
<Grammys>0</Grammys>
<link rel="self" href="http://dlwelchservices.com/jazz/artists/18" type="application/xml"/>
</Artist>
</Artists>
<Links>
<link rel="/jazz/rel/add" href="http://dlwelchservices.com/jazz/artists" type="application/xml"/>
<link rel="/jazz/rel/search" href="http://dlwelchservices.com/jazz/artists/?firstname={firstname}&lastname={lastname}&grammys={grammys}" type="application/xml"/>
<link rel="self" href="http://dlwelchservices.com/jazz/artists" type="application/xml"/>
</Links>
</JazzArtists>

Any errors generated by malformed requests or requests made to non-existent URIs should return standard HTTP error codes like 404 Not Found, 400 Bad Request, 405 Method Not Allowed and 500 Internal Server Error. For example, when a GET request is made to an artist resource that does not exist, our service returns a 404 Not Found status code and than presents the consumer with links to search or return to the bookmark URL:

404 Not Found
Allow: GET
Content-Type: application/xml; charset=utf-8
Location: http://dlwelchservices.com/jazz/artists/22
...
<?xml version="1.0" encoding="utf-8"?>
<JazzArtist xmlns="http://schemas.dlwelch.com/JazzService" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Artist/>
<Links>
<link rel="/jazz/rel/search" href="http://dlwelchservices.com/jazz/artists/?firstname={firstname}&lastname={lastname}&grammys={grammys}" type="application/xml"/>
<link rel="/jazz/rel/home" href="http://dlwelchservices.com/jazz/artists" type="application/xml"/>
</Links>
</JazzArtist>

Cache control is another standard feature of HTTP that allows our Jazz Web Service to adhere to the cache constraints of RESTful architectures. “Cache constraints require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable.”1 Since our service is quite small – only 20 maximum records are allowed – we are using an HTTP Cache-Control header of “no-cache” for all responses.

200 OK
Date: Mon, 01 Jul 2013 19:55:19 GMT
Allow: GET, PUT, DELETE
Content-Type: application/xml; charset=utf-8
Location: http://dlwelchservices.com/jazz/artists/2
Cache-Control: no-cache
...

If our service grows to the point that performance (whether on the server or client) becomes an issue, we can use a combination of HTTP standard headers like Cache-Control, Last-Modified, Age and Expires to explicitly define the cache-ability of each resource representation. We can also allow HTTP HEAD and conditional GET requests to help the client follow our cache-ability rules in accordance to our HTTP response headers.2

“All web services use HTTP, but they use it in different ways.”2 Using full-featured HTTP (as defined in RFC 2616) when making requests to resource URIs gives us a uniform interface that adheres to the REST constraints imposed upon web services in Resource-Oriented Architectures. You can follow the progress of our RESTful Jazz Web Service by navigating to the bookmark URI or using a jQuery/JavaScript client side application.


1. Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000.

2. Richardson, Leonard and Ruby, Sam. RESTful Web Services. Sebastopol: O’Reilly Media, Inc., 2008. Ebook

3. Fielding, Roy Thomas. REST APIs must be hypertext-driven. Untangled – Musings of Roy T. Fielding, October 20, 2008

4. Fielding, Roy Thomas, et. al. RFC 2616 – Hypertext Transfer Protocol – HTTP/1.1. The Internet Society, June 1999

Tagged with: ,
Posted in REST, Web Services
Advertisement