Julien Julien - 5 months ago 46
HTTP Question

REST API, HTTP status code and result code

This is more a "philosophical" question than a technical one.

Assume that you have a message, and users that are allowed (or not) to access this message.
Let's assume we have an api to do that, here would be the endpoints :

  • /message/(id_message)/allow/(user_id)

  • /message/(id_message)/forbid/(user_id)

Let's say now that, in addition to the HTTP status code, we have a field
that return a number that reflects exactly what happens in the code.

Let's say we allow the first time a user. The HTTP status code of this method should be 200, and let's say the
is 20.

If we straight call this method again, what should be the HTTP status code, the
, and why ?


Surely this is not a philosophical question but one about what the standard says and about real advantages of obeying these standards.

HTTP specifies GET, PUT and DELETE operations to be idempotent. This means that repeating the call needs to have the same effect.

Making these operations idempotent is important because messages can get lost and the caller needs to have a way to handle that. There are no transactions in REST, so repeating an idempotent operation ensures that it is carried out when the caller is unsure whether the first call had an effect. In your example allowing a user twice should be the same as allowing it once.

RFC7231 defines idempotence as follows:

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. [...] Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response. [...] It knows that repeating the request will have the same intended effect, even if the original request succeeded, though the response might differ.

The server side (main) effect needs to be the same. The RFC allows the response to be different. Especially in the case of DELETE this is often the case as a successful deletion normally results in a 204 No Content and a repeated deletion results in a 404 Not Found.

Although responses needn't be identical, it is nevertheless helpful if they are. This simplifies client logic. The client can assume that a repeated call has the same effect so it should be able to handle it using the same code. The aforementioned exception with DELETE returning either 204 or 404 is quite common (as this simplifies server logic). Other exceptions are rare and should be only made if there is a good reason for that.

POST and PATCH operations are, strictly speaking, not required to be idempotent. Especially with PATCH it can be helpful, though.

POST operations are meant to be not idempotent. Or rather the other way around: If you have an operation that you cannot make idempotent, it should be a POST operation.

Speaking of standards and REST: A REST resource for the purpose mentioned by you should rather look like the following:

GET /messages/{messageId}/allowed-users

Returns the list of allowed users. Note that resources which represent lists are named in plural (so messages not message).

PUT /messages/{messageId}/allowed-users/{userId}

Add a new user to the list of allowed users.

DELETE /messages/{messageId}/allowed-users/{userId}

Revoke the right previously given.

All these operations should be idempotent.

Using a POST operation would look like the following:

POST /messages/{messageId}/allowed-users

    "userId": "1324"

POST adds a new element to a list-like resource. You are not required to make this idempotent but I'd consider is advisable in this case.

You can return additional result codes as a header or as a result object. Just as you mentioned. But if you like to: there were some folks who already thought about that in detail and came up with problem-detail.