REST: Resources, Representations, and HTTP Semantics
- date
- category
- Backend
- also in
- Software Architecture · System Design
- reading
- 1 min / 290 words
REST is often reduced to a pattern:
GET /users
POST /users
DELETE /users/42
That is a useful convention, but it is not the definition of REST.
REST is an architectural style built, among other things, on resources, representations, statelessness and a uniform interface.
A resource is not a JSON record
Suppose a user exists:
/users/42
The identity of the resource is the URI.
JSON is one of its representations:
{
"id": 42,
"name": "Alice"
}
The same resource could in theory have a different representation:
Accept: application/json
or:
Accept: text/html
So REST separates:
resource
!=
representation
HTTP brings semantics
A well designed API uses the meaning of HTTP methods.
GET /users/42
reads a representation.
DELETE /users/42
removes the resource.
PUT /users/42
usually means replacing the representation.
PATCH /users/42
a partial modification.
This matters more than the aesthetics of URLs.
HTTP already has notions such as:
- safe methods,
- idempotency,
- cacheability,
- conditional requests.
An API can use them instead of building its own protocol inside POST.
Statelessness
Every request should carry the information needed to handle it.
That does not mean:
the server keeps no state.
The server of course keeps domain state.
The point is that there is no hidden conversational context required to understand the next request.
request N
request N+1
The second request should not depend on a local, temporary protocol session created by the first one, beyond explicitly modelled application state.
Where REST starts to feel awkward
Imagine an operation:
approve invoice
We can try to model it as a change of a resource:
PATCH /invoices/42
{
"status": "approved"
}
But is every domain operation really a simple field change?
What about:
recalculate invoice
send invoice
archive invoice
retry payment
generate report
Everything can be described with resources.
The question is whether it is always worth it.
If an API is strongly operational, the resource model can start to hide the real semantics of the domain.
The natural alternative then becomes RPC:
instead of: manipulate resource
we do: invoke operation
This is not a step "backwards".
It is a different API model.