Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct HTTP status code for a resource not found

For example, I need to find User resource with the following address api/user/1. In this case i am looking for exact resource with ID 1 and if resource does not exist, then 404 should be returned.

But what if I want to find exact latest user resource and it doesn't exist? For example, with address api/latest-user. Should 404 be returned now or 200 with empty results?

The thing that confuses me is that in both cases I am looking for a certain resource and if in the first case it is done by ID then in the second by order.

How to make this easier to understand and not to be misunderstood and what would be more understandable for the client?

like image 586
b00sted 'snail' Avatar asked Sep 18 '25 20:09

b00sted 'snail'


2 Answers

But what if I want to find exact latest user resource and it doesn't exist? For example, with address api/latest-user. Should 404 be returned now or 200 with empty results?

So the first thing to pay attention to is the meaning of each message

  • 404 the resource has no current representation, and the body of the response is an explanation for why this might be
  • 200 the resource has a current representation, and the body of the response is that representation

The status code is easy: you choose the status code that correctly describes the message. The challenging part is deciding whether your "resource" has a representation at the time of the request.

It's perfectly normal for a resource to have a representation even when there are no corresponding entities in your data layer. We might have an "empty" document, or lists with no items, or a representation composed entirely of default values. Those are all fine.

Search results are one obvious answer: you ask google, or stack overflow, for a representation of a list of documents, and at the time the list of documents is empty. So we get a representation of an empty list of documents, and the status code is... 200.

Loosely: 200 means "this is the current answer to your question", where 4xx means "I can't answer your question right now", and 404 is something more specific "I can't answer your question right now, because I have no idea what you are talking about".


Example:

https://www.youtube.com/watch?v=00000

What response do we get from the server if we try to GET that resource? What comes back (today: 2023-05-26) is a 200 response with a document that says "This video isn't available anymore". Why? because that's the current representation of the resource, and the 200 status code tells HTTP that the representation in the body of the response is the representation of the resource.

Notice: your web browser didn't get confused by that at all.


The larger idea: the status code is metadata of the transfer-of-documents-over-a-network domain. 200 tells us that we have successfully retrieved the document. Now we read the document to find out what's going on at the domain level, choosing the appropriate logical branch depending on the information that we find in the successfully retrieved document.

Or expressed another way: we should not (generally) repurpose HTTP metadata for our bespoke application.

like image 123
VoiceOfUnreason Avatar answered Sep 21 '25 12:09

VoiceOfUnreason


In REST modelling every endpoint represents a resource.

So both api/user/1 and api/latest-user represent resources that can be fetched from the server. api/latest-user should not be considered a function to be called where the function has its own existence independently of any results it might return. The conceptual model is flatter and simpler compared to to RPC styles like SOAP.

At a point in time where there are no user resources in the system, it is straightforward that the resource represented by api/latest-user is 'Not Found', and 404 would be a semantically correct status code, just as it is correct for a lookup by ID.

Probably more important than the semantics is the ease of use of your API! It will cause clients flow control difficulties if GET requests to 'api/latest-user' could return return either 200 with an empty body, or 200 with a serialized user. They will need to peek the stream of the response body in order to determine whether they are going to get a valid record, or possibly weaken the type of the response to [null|User] for deserializing in typesafe languages. If they knew the resource did not exist straight up from the status code they wouldn't even need to start reading the body.

Conversly if the resource were a collection e.g. api/user then returning 200 with an empty list would be semantically appropriate, as the collection is the resource and it exists, regardless of its length.

like image 25
Richard Woods Avatar answered Sep 21 '25 12:09

Richard Woods