Konrad Kowalski (rootsher)Principal Platform & Reliability Architect101110101111010010100001111100110111110011110010

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:

text
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:

text
/users/42

The identity of the resource is the URI.

JSON is one of its representations:

json
{
  "id": 42,
  "name": "Alice"
}

The same resource could in theory have a different representation:

http
Accept: application/json

or:

http
Accept: text/html

So REST separates:

text
resource
!=
representation

HTTP brings semantics

A well designed API uses the meaning of HTTP methods.

http
GET /users/42

reads a representation.

http
DELETE /users/42

removes the resource.

http
PUT /users/42

usually means replacing the representation.

http
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.

text
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:

text
approve invoice

We can try to model it as a change of a resource:

http
PATCH /invoices/42

{
  "status": "approved"
}

But is every domain operation really a simple field change?

What about:

text
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:

text
instead of: manipulate resource
we do: invoke operation

This is not a step "backwards".

It is a different API model.