The limited number of verbs in RESTful systems confuses and frustrates people new to the approach. What seem like arbitrary and unnecessary constraints are actually intended to encourage predictable behavior in non-application-specific ways. By explicitly and clearly defining the behavior of these verbs, clients can be self-empowered to make decisions in the face of network interruptions and failure.
There are four main HTTP verbs (sometimes called methods) used by well-designed RESTful systems.
The most common verb on the Web, a GET request transfers representations of named resources from a server to a client. The client does not necessarily know anything about the resource it is requesting. What it gets back is a bytestream tagged with metadata that indicates how the client should interpret it. On the Web, this is typically “text/html” or “application/xhtml+xml”. As we indicated above, using content negotiation, the client can be proactive about what is requested as long as the server supports it.
One of the key points about the GET request is that it should not modify anything on the server side. It is fundamentally a safe request. This is one of the biggest mistakes made by people new to REST. With RMM Level 1 systems, you often see URLs such as:
h t t p : // e x a m p l e . c o m / r e s / a c t i o n = u p d a t e ? d a t a = 1 2 3 4
Do not do this! Not only will RESTafarians mock you, but you will not build RESTful ecosystems that yield the desired properties. The safety of a GET request allows it to be cached.
GET requests are also intended to be idempotent. This means that issuing a request more than once will have no consequences. This is an important property in a distributed, network-based infrastructure. If a client is interrupted while it is making a GET request, it should be empowered to issue it again because of the idempotency of the verb. This is an enormously important point. In a well-designed infrastructure, it does not matter what the client is requesting from which application. There will always be application- specific behavior, but the more we can push into non- application-specific behavior, the more resilient and easier to maintain our systems will be.
The situation gets a little less clear when we consider the intent of the POST and PUT verbs. Based on their definitions, both seem to be used to create or update a resource from the client to the server. They have distinct purposes, however.
POST is used when the client cannot predict the identity of the resource it is requesting to be created. When we hire people, place orders, submit forms, etc., we cannot predict how the server will name these resources we are creating. This is why we POST a representation of the resource to a handler (e.g. servlet). The server will accept the input, validate it, verify the user’s credentials, etc. Upon successful processing, the server will return a 201 HTTP response code with a “Location” header indicating the location of the newly created resource.
Note: Some people treat POST like a conversational GET on creation requests. Instead of returning a 201, they return a 200 with the body of the resource created. This seems like a shortcut to avoid a second request, but it also conflates POST and GET and complicates the potential for caching the resource. Try to avoid the urge to take shortcuts at the expense of the larger picture. It seems worth it in the short- term, but over time, these shortcuts will add up and likely work against you.
Another major use of the POST verb is to “append” a resource. This is an incremental edit or a partial update, not a full resource submission. For that, use the PUT operation. A POST update to a known resource would be used for something like adding a new shipping address to an order or updating the quantity of an item in a cart.
Because of this partial update potential, POST is neither safe nor idempotent.
A final common use of POST is to submit queries. Either a representation of a query or URL-encoded form values are submitted to a service to interpret the query. It is usually fair to return results directly from this kind of a POST since there is no identity associated with the query.
Note: Consider turning a query like this into an information resource itself. If you POST the definition into a query information space, you can then issue GET requests to it, which can be cached. You can also share this link with others.
Many developers largely ignore the PUT verb because HTML forms do not currently support it. It serves an important purpose, however, and is part of the full vision for RESTful systems.
A client can issue a PUT request to a known URL as a means of passing the representation back to the server in order to do an overwrite action. This distinction allows a PUT request to be idempotent in a way that POST updates are not.
If a client is in the process of issuing a PUT overwrite and it is interrupted, it can feel empowered to issue it again because an overwrite action can be reissued with no consequences; the client is attempting to control the state, so it can simply reissue the command.
Note: This protocol-level handling does not necessarily preclude the need for higher (application-level) transactional handling, but again, it is an architecturally desirable property to bake in below the application level.
PUT can also be used to create a resource if the client is able to predict the resource’s identity. This is usually not the case, as we discussed under the POST section, but if the client is in control of the server-side information spaces, it is a reasonable thing to allow.
The DELETE verb does not find wide use on the public Web (thankfully!), but for information spaces you control, it is a useful part of a resource’s lifecycle.
DELETE requests are intended to be idempotent, so you should generally build resources that respond to DELETE requests by failing silently and returning a 204 (No Content) even if the resource has already been deleted. Some security policies may require you to return a 404 for non-existent or deleted resources so DELETE requests do not leak information about the presence of resources.
There are three other verbs that are not as widely used but provide value.
The HEAD verb is used to issue a request for a resource without actually retrieving it. It is a way for a client to check for the existence of a resource and possibly discover metadata about it.
The OPTIONS verb is also used to interrogate a server about a resource by asking what other verbs are applicable to the resource.
The newest of the verbs, PATCH was only officially adopted as part of HTTP in early 2010. The goal is to provide a standardized way to express partial updates. Because POST can be used for anything, it is unclear when it is being used for partial updates.
A PATCH request in a standard format could allow an interaction to be more explicit about the intent. There are RFCs from the IETF for patching XML and JSON.
If the client issues a PATCH request with an If-Match header, it is possible for this partial update to become idempotent. An interrupted request can be retried because, if it succeeded the first time, the If-Match header will differ from the new state. If they are the same, the original request was not handled and the PATCH can be applied.