Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST HTTP response code for missing parent resource

My question is, should I return a HTTP response code of 400 Bad Request, 404 Not Found or 410 Gone when a parent resource, or higher, does not exist / has been deleted?

Looking for some guidance around how to handle a missing links in a RESTful resource tree, as I've read quite a bit but not a whole lot of personal experience.

Say we have the resources structure below:

/users/{userId}/accounts/{accoundId}/logs/{logId}

One user can have many accounts, which in turn can have many orders, which in turn can have many logs. Logs only exist against a single account, and accounts only exist against a single user. Logs cannot exist without an account, and accounts cannot exist without a user.

My problem comes when I try to resolve the below:

/users/123/accounts/321/logs - POST
/users/123/accounts/321/logs/987 - GET
/users/123/accounts/321/logs/987 - PUT
/users/123/accounts/321/logs/987 - DELETE
/users/123/accounts/321/logs/987 - PATCH
/users/123/accounts/321/logs/987 - HEAD

But this resource does not, or no longer, exists:

/users/123/accounts/321

or this resource does not, or no longer, exists:

/users/123

I could argue it's a 400 Bad Request, which as per RFC7231:

6.5.1. 400 Bad Request

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).

Would be by definition true, except in the scenario that a cache hadn't expired, meaning the application had yet to re-traverse the hierarchy, and another application had deleted the parent resource. By providing a relevant oplock, the client will have proven that as per its last knowledge, it was making a semantically correct request.

I instinctively would have lent towards 404 Not Found or 410 Gone even if this wasn't a cache thing, as the cause of the failure was literally a missing/unavailable resource. However as per the spec RFC7231:

6.5.4. 404 Not Found

The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or
permanent; the 410 (Gone) status code is preferred over 404 if the
origin server knows, presumably through some configurable means, that the condition is likely to be permanent.

or

6.5.9. 410 Gone

The 410 (Gone) status code indicates that access to the target
resource
is no longer available at the origin server and that this
condition is likely to be permanent.

These would appear to give the lie to that instinct.

Does anyone have any experience in dealing with this, or similar, scenarios and good approaches? I feel I should go with what feels right and what I'd expect to see if consuming this service, rather than the letter of the text.

like image 727
It's an account Avatar asked Jan 25 '18 18:01

It's an account


People also ask

What is the HTTP error response code for when a resource is not found?

404: “The requested resource was not found.” This is the most common error message of them all. This code means that the requested resource does not exist, and the server does not know if it ever existed.

When should I use HTTP 404?

If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. This response is cacheable unless indicated otherwise.

What is http code1?

We tend to get -1 status codes when there are network issues or connection problems, so we display the user a network problems page in those cases.

What is the difference between HTTP status code 200 and 201?

The 200 status code is by far the most common returned. It means, simply, that the request was received and understood and is being processed. A 201 status code indicates that a request was successful and as a result, a resource has been created (for example a new page).


2 Answers

A thing to keep in mind: the HTTP response, including the metadata, which includes the status code, are specific to the requested resource, not some implicit hierarchy of things.

Which is to say

GET /users/{userId}/accounts/{accoundId}/logs/{logId}

requests: a current selected representation for the target resource. See RFC 7231; in particular, the request doesn't ask about representations of any of these:

/users/{userId}/accounts/{accoundId}/logs/
/users/{userId}/accounts/{accoundId}/
/users/{userId}
...

It's much simpler than that - can I have what I asked for? And the origin server provides a response, which may be a current representation, or it may be a message explaining that no such representation is available.

The fact that no representation of /users/{userId}/accounts/{accoundId}/logs/{logId} is available because /users/{userId}/accounts/{accoundId} does not exist is an implementation detail.

404 is normally what you would want to use as a status code to announce that no current representation of the target resource is available. Any explanation for why this is the case would normally go into the message body. For instance, you might describe it using problem details.

The server is not obligated to send an expired representation of a resource just because it happens to have one lying around (again, the cache is an implementation detail).

410 is almost the same thing; it's effectively an advisory that the client can mark its bookmarks as deprecated.

400 is a perfectly reasonable way to punt if you can't find a status code that better fits the semantics of the message in the payload. But I wouldn't use if for this case where 404 does actually fit your needs.

like image 67
VoiceOfUnreason Avatar answered Nov 10 '22 15:11

VoiceOfUnreason


NO: Rule out the 400 Bad Request as all the requests, which you have mentioned, are valid.

NO: To add some spice: I've seen a 409 Conflict being returned in similar cases. It appears inappropriate in your situation though as you clearly indicated that a resource is missing.

YES: A 404 Not Found is the most appropriate response if your resource does not exist. It doesn't matter if it ever existed or not. The 404 indicates a "sorry, resource unavailable". I would add an error message to be precise about which resource is missing so that your API consumers can handle the situation better.

MAYBE: A 410 Gone is a specific case of a 404. It should be raised if the resource is unavailable and it existed before and it will (practically) never exist again. So no matter how often and when you try to get the resource, you'll never get it again, but in the past, you may have been able to get it. Same thing here: if you decided on a 410 consider adding a precise error message.

On a personal note:

  • I have never seen a practical useful situation of a 410 Gone hence I avoid it and recommend my teams not to use it unless they can come up with a real good reason. It appears a little academic. In most cases, a 404 and 410 will be dealt with identically by your API consumers. They most often don't mind/care. I can only see rare edge cases to make valuable sense of a differentiation.
  • A DELETE often doesn't delete a resource. They get inactivated (made unavailable), but they are still available technically. If there's any chance that a resource may become available again, such as via a new feature called "return all recently deleted resources", a 410 would be already misleading.
  • A 410 also states that that resource did exist in the past indeed. From a data securities point of view, you could argue that information should kept internal and should not be exposed. In these cases, a 410 becomes a general no-no for your API.
like image 38
Quality Catalyst Avatar answered Nov 10 '22 16:11

Quality Catalyst