Reputation: 462
I have a REST API and want to implement different states for some resources. The API is at the Level 2 of the Richardson Maturity Model.
I've seen a lot of different approaches regarding the endpoints for changing the states, but I'm not sure what's the recommended one.
My scenario is the following: My entities are orders. An order can be open, closed and in progress.
PATCH
request to /orders/{id}
with the request body{
"state": "in-progress"
}
/orders/{id}/status/in-progress
and make a POST
request to trigger that action. But that would have a smell of RPC.PUT
request to update it. /orders/{id}/state
{
"state": "in-progress"
}
In addition to that, I'm not sure what should be in the response body.
202 Accepted
without body.200 Ok
with the updated state as body.{
"state": "in-progress"
}
200 Ok
with the order and it's updated state as body.{
"id": 1
"state": "in-progress"
}
200 Ok
with the order and it's updated state + the next possible states as body. This feels like a small step towards Hypermedia / Maturity Level 3.{
"id": 1
"state": "in-progress"
"nextStates": ["closed"]
}
There are a lot of opportunities. It seems like that I can't model the endpoints like resources, how it's should be done for RESTful APIs. But I also don't want to use actions like in RPC. And I know it's only REST if you have Hypermedia but that's to complex and pricey to implement.
Upvotes: 0
Views: 1243
Reputation: 57299
The basic idea: resources are abstractions of documents. A client sends information to the server by requesting modifications to documents. Useful business activity is a side effect triggered by the modifications to the documents.
So if your client want to tell the server about the state of an order, then the idea is to find the document with the state information, and to send a message requesting that document be modified.
On the web, we do this by submitting forms - little messages describing the change we want to make to the document. That might look like
POST /orders/12345
Content-Type: application/x-www-form-urlencoded
action=changeState&state=in-progress
Another alternative is to edit the document locally, and then send the server a copy of the edited document
PUT /orders/12345
Content-Type: application/json
{
"id": "12345",
"items": [
"loaf of bread",
"container of milk",
"stick of butter"
],
"state": "in-progress"
}
The schema here is the same that was provided to us by "GET /orders/12345", we're sending the entire document back to the server, including our changes.
When the document is very large (relative to the HTTP headers), and the change is small, then we might instead prefer to send a patch document that describes the changes. For example
PATH /orders/12345
Content-Type: application/json-patch+json
[ {"op":"replace", "path":"/state", "value":"in-progress"} ]
It's the same idea as with PUT: we've made changes to our copy of the document, and we ask that the server changes its copy of the document to match ours.
In addition to that, I'm not sure what should be in the response body.
200 OK, with either
The metadata (in particular, the Content-Location header) tells the client which is which.
Upvotes: 0