5

In my REST API I have the normal CRUD endpoints for some resources. If I do a GET /items/42 and there is no such item, the normal behaviour would be to return a 404 NOT FOUND.

However, one scenario concerns me. In this scenario, a client needs to check if a resource (which is implicitly idenfitied by a token) exists, and if not, create it. So, the client would try to retrieve the resource, and if a 404 is received the client application would display the UI necessary for creating the item, and then proceed to POSTing the new resource. In a way, this is a special kind of resource, because since its ID is derived from other parameters, it's known even before creation. As an example, consider a user sign-up procedure; the client would ask "Do I exist? If no -> register me".

My concern is really whether I ever need to worry about "spurious" 404:s? Considering a server is usually surrounded by API gateways, reverse proxies and such, is there any risk that a 404 NOT FOUND could be produced by a surrounding entity due to some temporary error not related to the REST server itself? If so, it could trick the client into believing that the item is not created yet, and that it should now be created. Even if the resulting POST request to create the item would fail because the item already exists, this isn't very nice because the user may have entered data etc for no reason.

Is this a problem to take into account or just overly paranoid? I guess if clients can't trust a 404 to be idempotent (until the resource is created, of course), many other issues arise. Is there any actual situation where an API gateway or similar would report a 404 on its own?

If this is a valid scenario, do I need a "safer", more explicit response saying that the request definetely succeeded but the resource wasn't found, such as responding with a 200 OK with an empty JSON body or a {isRegistered: false}, a 204 NO CONTENT, or similar? This opens up for other strange things - if a request for a resource that doesn't exist would respond with a 200 accompanied by an empty body, perhaps creation of the item would be a PUT rather than a POST, etc? This seems like a can of worms... It all boils down to "Does a 404 guarantee that the given resource doesn't exist?".

1 Answer 1

3

404 is pretty unambiguous : the resource wasn't found and it's a client error (4xx). Normally, server-side errors (5xx) can't interfere and create spurious 404's here.

As an alternative, if the resource to be created is linked to another resource in a unique way, you could use OPTIONS to ask the server if it already exists.

For instance :

OPTIONS /visitors/7883930/user-account 

=> Allow: POST,OPTIONS (doesn't exist)

=> Allow: GET,OPTIONS (exists)

The key here is to have a URI that allows accessing the resource without knowing its ID. It is not always possible though.

Sign up to request clarification or add additional context in comments.

4 Comments

Right. I didn't consider that the entire 4xx range is defined as client errors, that's a really good point. So I guess it's pretty safe to assume that if, say, nginx has an intermittent problem reaching the resource server, it would never return a 404. Typically I guess it would return something in the 5xx range?
Using OPTIONS was an interesting approach, it may not be the most straightforward technique familiar to most clients, but definetely worth remembering. And yes, in my particular case the URI is derived from information passed through headers etc (e.g. in the form of an authentication token), so that the client can request for example the URI /me to get his/her user profile.
Though I don't know nginx, I would expect more of a 504 Gateway Timeout than a 500 in that case. But yes, definitely not a 404.
Actually, a misconfigured nginx may very well return a 404 if it does not know what to do with a request. I just tested with the lastest nginx docker image. Result when trying to access /abc on it: <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.21.0</center> </body> </html>

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.