Safety, Idempotence, and the Resource-Oriented Architecture (Page 1 of 5 )
Appending to the resource state
The information conveyed in a POST to a resource doesnít have to result in a whole new subordinate resource. Sometimes when you POST data to a resource, it appends the information you POSTed to its own state, instead of putting it in a new resource.
Consider an event logging service that exposes a single resource: the log. Say its URI is /log. To get the log you send a GET request to /log.
Now, how should a client append to the log? The client might send a PUT request to /log, but the PUT method has the implication of creating a new resource, or overwriting old settings with new ones. The client isnít doing either: itís just appending information to the end of the log.
The POST method works here, just as it would if each log entry was exposed as a separate resource. The semantics of POST are the same in both cases: the client adds subordinate information to an existing resource. The only difference is that in the case of the weblog and weblog entries, the subordinate information showed up as a new resource. Here, the subordinate information shows up as new data in the parentís representation.
Overloaded POST: The not-so-uniform interface
That way of looking at things explains most of what the HTTP standard says about POST. You can use it to create resources underneath a parent resource, and you can use it to append extra data onto the current state of a resource. The one use of POST I havenít explained is the one youíre probably most familiar with, because itís the one that drives almost all web applications: providing a block of data, such as the result of submitting a form, to a data-handling process.
Whatís a ďdata-handling processĒ? That sounds pretty vague. And, indeed, just about anything can be a data-handling process. Using POST this way turns a resource into a tiny message processor that acts like an XML-RPC server. The resource accepts POST requests, examines the request, and decides to do... something. Then it decides to serve to the client... some data.
I call this use of POST overloaded POST, by analogy to operator overloading in a programming language. Itís overloaded because a single HTTP method is being used to signify any number of non-HTTP methods. Itís confusing for the same reason operator overloading can be confusing: you thought you knew what HTTP POST did, but now itís being used to achieve some unknown purpose. You might see overloaded POST called POST(p), for ďprocess.Ē
When your service exposes overloaded POST, you reopen the question: ďwhy should the server do this instead of that?Ē Every HTTP request has to contain method information, and when you use overloaded POST it canít go into the HTTP method. The POST method is just a directive to the server, saying: ďLook inside the HTTP request for the real method information.Ē The real information may be in the URI, the HTTP headers, or the entity-body. However it happens, an element of the RPC style has crept into the service.
When the method information isnít found in the HTTP method, the interface stops being uniform. The real method information might be anything. As a REST partisan I donít like this very much, but occasionally itís unavoidable. By Chapter 9 youíll have seen how just about any scenario you can think of can be exposed through HTTPís uniform interface, but sometimes the RPC style is the easiest way to express complex operations that span multiple resources.
You may need to expose overloaded POST even if youíre only using POST to create subordinate resources or to append to a resourceís representation. What if a single resource supports both kinds of POST? How does the server know whether a client is POSTing to create a subordinate resource, or to append to the existing resourceís representation? You may need to put some additional method information elsewhere in the HTTP request.
Overloaded POST should not be used to cover up poor resource design. Remember, a resource can be anything. Itís usually possible to shuffle your resource design so that the uniform interface applies, rather than introduce the RPC style into your service.