RESTful Web Services for Resource-Oriented Architectures (ROA) – Part 4 – Statelessness

The second constraint Dr. Fielding places on RESTful architectures is that of Statelessness. In a RESTful web service, “communication must be stateless in nature … such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.” 1

In a Resource Oriented Architecture, Richardson and Ruby define two types of state: application (or session) state which is the responsibility of the client and resource state which is held on the server.2 To illustrate the difference in the two types of state, consider the banking service found in our previous post RESTful Web Services for Resource-Oriented Architectures (ROA) – Part 2 – HATEOAS. Pending transactions are not kept in a session controlled by the server. The server does not wait for and is not expecting the client to proceed through the completion of the posting process in any particular order or timeline. Instead, pending transaction are resources stored on the server. It is up to the client to retrieve the transactions and then decide whether to post, edit or delete them. The client determines the next step he wants to take and when he will take it. The server responds with an appropriate answer – in the form of another resource – to the client’s requests. If the client tries to POST, PUT or DELETE an invalid resource, the server simply returns another resource indicating failure and containing links that can lead the client to a remedy.

Suppose our banking service returns the following resource when a client makes a GET request to “/bank/transferforms/dlwelch”. The response contains a list of all pending and posted transfer transactions for account dlwelch.

200 OK
Allow: GET, POST
Content-Type: application/xml; charset=utf-8
Location: "/bank/transferforms/dlwelch"

  <transferforms>
    <pendingforms>
      <form> 
        <id>1235</id>
        <link rel="self"  type="application/xml"
              uri="/bank/transferforms/dlwelch/pending/1235" />
      </form>
      <link rel="self"  type="application/xml"
            uri="/bank/transferforms/dlwelch/pending" />
    </pendingforms>
    <postedforms>
      <form> 
        <id>0001</id>
        <link rel="self"  type="application/xml"
              uri="/bank/transferforms/dlwelch/posted/0001" />
      </form>
      ...
      <form> 
        <id>1234</id>
        <link rel="self"  type="application/xml"
              uri="/bank/transferforms/dlwelch/posted/1234" />
      </form>
      <link rel="self"  type="application/xml"
            uri="/bank/transferforms/dlwelch/posted" />
    </postedforms>
    <link rel="self" type="application/xml" 
          uri="/bank/transferforms/dlwelch" />
    <link rel="up" type="application/xml" 
          uri="/bank/accounts/dlwelch" />
    <link rel="/bank/rel/home" type="application/xml" 
          uri="/bank" />
    <link rel="/bank/rel/create" type="application/xml" 
          uri="/bank/transferforms/dlwelch" />
  </transferforms>

As described in our previous article, the client can finish a pending transaction by submitting a POST request to the pending transaction’s URL. But if we tried to POST to “/bank/transferforms/dlwelch/pending/1234″, our banking service should return an error response, for example:

410 GONE
Content-Type: application/xml; charset=utf-8
Location: "/bank/transferforms/dlwelch/pending/1234"

<error>
  <link rel="/bank/rel/transfers" type="application/xml" 
       uri="/bank/transferforms/dlwelch" />
  <link rel="/bank/rel/accounts" type="application/xml" 
       uri="/bank/accounts/dlwelch" />
  <link rel="/bank/rel/customers/dlwelch/" type="application/xml" 
       uri="/bank/customers/dlwelch/" />
  <link rel="/bank/rel/home" type="application/xml" 
       uri="/bank" />
</error>

This response tells us the resource located at “/bank/transferforms/dlwelch/pending/1234″ existed at one time but has been permanently moved or deleted.

All responses from a RESTful service – including error messages – are returned to the client as useful resource representations that guide the client to an acceptable state. A RESTful service, due to its stateless nature, never requires the client to be in a particular state in order to provide an appropriate, valid response to the client’s request. The service will not become confused or inoperable because the client does not follow a pre-defined process flow. And it will not re-post our transfer or re-submit an online payment – even when the user hits the back button.

“HTTP is an intrinsically stateless protocol, so when you write a web service you get statelessness by default. You have to do something to break it. The most common way to break statelessness is to use your framework’s version of HTTP sessions.” 2 Take, for example, ASP.NET session state. “ASP.NET session state enables you to store and retrieve values for a user as the user navigates ASP.NET pages in a Web application. HTTP is a stateless protocol. This means that a Web server treats each HTTP request for a page as an independent request. The server retains no knowledge of variable values that were used during previous requests. ASP.NET session state identifies requests from the same browser during a limited time window as a session, and provides a way to persist variable values for the duration of that session. By default, ASP.NET session state is enabled for all ASP.NET applications.” 5 ASP.NET purposely breaks the natural statelessness of HTTP. By retaining session identifiers and variables on the server, an ASP.NET web application can dictate the application state to the client. For an ASP.NET developer, the first thing to do when moving to a RESTful ROA is to abandon any ideas about sessions.

Instead of sessions and methods, start thinking about resources and representations. “A (RESTful) web service only needs to care about your application state when you’re actually making a request. The rest of the time it doesn’t even know you exist. This means that whenever a client makes a request, it must include all the application states the server will need to process the request.”2 If you get stuck trying to remove application state from the server, ask yourself how you would accomplish the same task using hard-copy documents. Our banking service works the same way as when we present a paper check at the bank teller window. We need to show a drivers license (authentication), a valid check made out to the bearer (authorization) and a deposit slip for our account (URI request). In return we will receive a deposit receipt or cash (resource representation) depending on the resource request we submitted.

The Jazz Artist web service discussed in previous posts is a stateless service. The client can make a request to any URI, in any order, without the server having knowledge of previous requests. The server considers each client request in isolation and then returns a RESTful response – even if the returned representation is an error report.

400 Bad Request
Date: Fri, 01 Nov 2013 19:27:21 GMT
Server: Microsoft-IIS/7.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Type: application/xml; charset=utf-8
Location: http://dlwelchservices.com/jazz/badrequest?aspxerrorpath=/jazz/artists/125*
Cache-Control: no-cache
Content-Length: 503
<?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/>
<Links>
<link rel="/jazz/rel/home" 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"/>
</Links>
</JazzArtists>

It is up to the client application to manage state and works it’s way through our service in a meaningful progression using the information provided by the response.


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

5. MSDN Library – ASP.NET Session State Overview – .Net 4

Tagged with: ,
Posted in REST, Web Services
Advertisement