Question

I'm designing a RESTful API that is using the HTTP status codes and verbs as key components in communicating.

On the religious level it's on the zealot side of RESTafarian.

Rule of thumb for deciding HTTP status codes has been this graph, or similar resources.

  • GET /api/documents/1 - 401 User has not logged in
  • GET /api/documents/1 - 200 User has permission
  • GET /api/documents/1 - 403 User does not have permission
  • DELETE /api/documents/1 - 204 Users has permission
  • DELETE /api/documents/1 - 403 User does not have permission
  • GET /api/documents/2 - 404 Users permission irrelevant, resource does not exist
  • DELETE /api/documents/2 - 404 Users permission irrelevant, resource does not exist
  • DELETE /api/documents/1 - 404 Users has permission, resource already deleted
  • DELETE /api/documents/1 - 404 Users does not have permission, resource already deleted

Goals:

  • Consistency in usage
  • Not to expose private information through errors
  • Proper use of status codes for client or middle layer caches
  • Fail early, keep lookups to a minimum

In this situation there is a lot of different status code to chose from ( 404, 403, 410, 405) and in my case I went with 403 on a existing resource if its not yours to not clear the cache, and 404 on all non existing resources so to tell the clients to wipe that data.

But I do not like the switch from 403 to 404 on resources that are not yours.

I'm interested to hear from others how you solved this use-case, or in general what status codes you feel appropriate to send in all invalid DELETE calls, since I deem that as one of the hardest to be concise with.

(A lot of REST discussions and answers on the internet in it whole are just "Throw a 400 bad request, no one cares anyway", I do not have a problem that needs a quick fix or a pragmatic hack. Thanks)

Was it helpful?

Solution

General pointer: In case a resource exists but a user is not authorized to perform operations on it, you should return 401 over 403:

401 Unauthorized

Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.

and

403 Forbidden

The request was a valid request, but the server is refusing to respond to it. Unlike a 401 Unauthorized response, authenticating will make no difference.

See also Correct HTTP status code when resource is available but not accessible because of permissions


I went with 403 on a existing resource if its not yours to not clear the cache, and 404 on all non existing resources so to tell the clients to wipe that data.

As pointed out earlier, 401 should be used instead of 403. 404 is ok to return if you just want to say "sorry, resource not found". If you however want to say "resource was here but it's not anymore and never again will be" (this appears to be the case in your situation) you can return 410:

410 Gone

Indicates that the resource requested is no longer available and will not be available again. This should be used when a resource has been intentionally removed and the resource should be purged. Upon receiving a 410 status code, the client should not request the resource again in the future. Clients such as search engines should remove the resource from their indices


To summarize, this is how I would implement it in your case. The changes I made are in bold.

  • GET /api/documents/1 - 401 User has not logged in
  • GET /api/documents/1 - 200 User has permission
  • GET /api/documents/1 - 401 User does not have permission
  • DELETE /api/documents/1 - 204 User has permission
  • DELETE /api/documents/1 - 403 User does not have permission
  • GET /api/documents/2 - 404 Users permission irrelevant, resource does not exist
  • DELETE /api/documents/2 - 404 Users permission irrelevant, resource does not exist
  • DELETE /api/documents/1 - 410 User has permission, resource already deleted
  • DELETE /api/documents/1 - 401 User does not have permission, resource already deleted

For the last one, you can return 401 if you do not want the unauthorized user to know that there was a resource that has already been deleted. If you don't care you can return 410. That is for you to decide.

I do not like the switch from 403 to 404 on resources that are not yours.

It's perfectly fine to return different status codes depending on what the situation is.

I hope this helps you out a bit.

OTHER TIPS

The response code for an invalid delete call depends on what the failure is. In your cases, I would go with:

  • DELETE /api/documents/1 - Users has permission
    • 204 No Content
  • DELETE /api/documents/2 - Users permission irrelevant, resource does not exist
    • 404 Not Found
  • DELETE /api/documents/1 - Users has permission, resource already deleted
    • 410 Gone
  • DELETE /api/documents/1 - Users does not have permission, resource already deleted
    • 403 Forbidden

The last call is the only one worth really talking about. I believe (and your graph agrees) that the user's lack of permission takes precedence over the resource already being deleted. If the user were to get a 410, then you'd be leaking information (resource already deleted).

As far as 401/403, 401 is "you haven't logged in yet". 403 is "you have logged in, and you don't have permission to do what you want". I don't see anything unusual in your usage of those codes.

Having said all this, I feel like I'm somehow misinterpreting the question.

I don't like the idea of a 404 as representing a failed delete where the resource cannot be found (or for a put or patch for that matter). It is fairly common to have DNS issues and for people to have parameter based routing issues that would both yield a 404 if the actual site could not be found. Introducing this type of ambiguity can make diagnosing simple problems really and unnecessarily difficult. I think 410 Gone is a better choice for representing a resource not found when it comes to APIs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top