I read the part about not using 404s twice and I still don’t quite get it. It sounds like the author was using some infrastructure separate from their actual app server that unpredictably returned 404 responses and thus they don’t want to deliberately return 404 responses?
Not the author, but I think the idea is to avoid overloading the meaning of 404. They argue 404 should mean the request didn't match a known route, in case the request is recognized but the record itself isn't found you should return a different 4xx code
I kind of get this and wouldn't complain about an API doing this, but I also wouldn't be surprised for `/api/v1/posts/abc-123` to return 404 because the route handler couldn't match the post ID.
They are attempting to argue that 404 is ambiguous, so we should avoid it. They do not to my eyes meaningfully highlight a replacement outside of some very specific cases.
I strongly disagree with this stance as I don't think 404 is ambiguous at all.
Although it would be useful to know at what point in the broader hierarchy of a specific resource requested the unavailability starts: Ultimately 404 just means the specific 'tip of the spear' resource requested is not found.
The thing about 404, is that you can both return 404 as well as an error document that has the structure the author is looking for, which means there is no reason why you can't return a 404 status.
Got 404, returned body is json, returned body is an error object, good to go.
Oh and, by returning a 404 you help intermediate caches know that they should not cache the response.
English pluralisation rules are a non issue. 1.5 billion people world wide speak English, and I'll forgive some of them if they accidentally make a gooses URL instead of a geese one.
Why have plural at all. All rest urls except index, which is easily discernible because it has no id, make more sense in the singular:
get /ticket/12
patch /ticket/12
put /ticket
The problem is not humans getting confused by 'gooses', but that sometimes your code has to do the mapping, and there are plenty of edge-cases. Just avoid the issue entirely by sticking with singular throughout.
It basically means, "We received and understood your request, but you're not getting a response." And you can infer that it's because the content you requested is not there.
At a previous company, we returned a 200 for anything that was not a true HTTP error on our side, with a dedicated error message in the response for anything else. So, for instance, instead of returning a 403 when the API user provided invalid data, we would return a 200, indicating that we successfully did everything we were supposed to do, but then explained in the response what invalid data needed to be corrected.
I liked that approach. Anything non-200-level meant that we screwed up. And any 200-level response with an error message meant that the user screwed up.
But HTTP 204 is also appropriate for a some POST requests where a response is unnecessary or sometimes not even possible (e.g. browser-based "beacon" requests during onunload[1]), so if you use 204 to represent entity-does-not-exist then you need to re-think how to handle no-response-responses.
As an alternative to using HTTP 404 for detecting a misconfigured server with bad routing, you could use the "Server" response header to include an invariant indicator as a confidence sign to the client that the HTTP 404 response does not mean bad-routing or misconfigured server - or expired-domain-name-now-points-to-a-domain-squatting-website.
If it worked for you, that's fine... but this is completely counter to how most HTTP applications work and definitely not a best practice. Both returning errors or the interpretation of the meaning of 204.
The author at least suggests using 400, which at the very least will make clients and proxies behave in a predictable way, but ideally you just return the appropriate HTTP status code, and use a well-defined response body to indicate why the specific error was returned.
> At a previous company, we returned a 200 for anything that was not a true HTTP error on our side
I work at a company that does this and it is beyond annoying. We've had multiple discussions between the dev team and we chalk it up the difference between application developers, who want the error codes to reflect the state of the application, and network engineers, who want the error codes to reflect the state of the network. Both sides have merit, but as an app developer I really hate the networking engineer approach to this.
Have you not heard of 500 errors? How about 400 for "bad request"?
Seriously, stop reinventing what is already an established standard. There is nothing more annoying than a server that returns a 200-class status when the thing I requested is not in the response.
I like very much something I saw in the Dropbox API:
All application errors are returned with a 409 code, and then you are sure to have a properly json formatted error in the body that can will have an error code more relevant for your case.
I would extend Rule 6 much more into Rule 7 - if you're returning an id which is numeric, prefix it with a non-number, so it won't get accidentally converted to a number. This has been a particular pain with Perl (yes, it's still used in place) JSON libraries, where knowing if you're going to serialise to a string or a number is quite dependent on how the variable has been touched - so things like stringifying it in a debug line might change the output.
If you make it so your ID is never something that Excel can incorrectly assume is a date, you're making life better for everybody.
The author should keep the examples consistent, it was showing good example first then bad examples then all of a sudden it swapped to bad example first then good which goes against his Rule #9.
20 comments
[ 6.3 ms ] story [ 58.4 ms ] threadI took it to mean 404 should mean you haven't hit the API at all.
I kind of get this and wouldn't complain about an API doing this, but I also wouldn't be surprised for `/api/v1/posts/abc-123` to return 404 because the route handler couldn't match the post ID.
I strongly disagree with this stance as I don't think 404 is ambiguous at all. Although it would be useful to know at what point in the broader hierarchy of a specific resource requested the unavailability starts: Ultimately 404 just means the specific 'tip of the spear' resource requested is not found.
Got 404, returned body is json, returned body is an error object, good to go.
Oh and, by returning a 404 you help intermediate caches know that they should not cache the response.
I disagree, as you then have to deal with English pluralization rules to match single objects and collections.
Also database tables should just be singular, things like 'country.id' makes more sense than 'countries.id'.
Also no discussion of versioning?
The author says it's ambiguous, because it could mean the route is not found, or it could mean the requested item is not found.
Some people use 204 to indicate the latter:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204
It basically means, "We received and understood your request, but you're not getting a response." And you can infer that it's because the content you requested is not there.
At a previous company, we returned a 200 for anything that was not a true HTTP error on our side, with a dedicated error message in the response for anything else. So, for instance, instead of returning a 403 when the API user provided invalid data, we would return a 200, indicating that we successfully did everything we were supposed to do, but then explained in the response what invalid data needed to be corrected.
I liked that approach. Anything non-200-level meant that we screwed up. And any 200-level response with an error message meant that the user screwed up.
As an alternative to using HTTP 404 for detecting a misconfigured server with bad routing, you could use the "Server" response header to include an invariant indicator as a confidence sign to the client that the HTTP 404 response does not mean bad-routing or misconfigured server - or expired-domain-name-now-points-to-a-domain-squatting-website.
[1] https://developer.mozilla.org/en-US/docs/Web/API/Navigator/s...
The author at least suggests using 400, which at the very least will make clients and proxies behave in a predictable way, but ideally you just return the appropriate HTTP status code, and use a well-defined response body to indicate why the specific error was returned.
I work at a company that does this and it is beyond annoying. We've had multiple discussions between the dev team and we chalk it up the difference between application developers, who want the error codes to reflect the state of the application, and network engineers, who want the error codes to reflect the state of the network. Both sides have merit, but as an app developer I really hate the networking engineer approach to this.
Seriously, stop reinventing what is already an established standard. There is nothing more annoying than a server that returns a 200-class status when the thing I requested is not in the response.
All application errors are returned with a 409 code, and then you are sure to have a properly json formatted error in the body that can will have an error code more relevant for your case.
So that could be NOT_FOUND in such a case.
If you make it so your ID is never something that Excel can incorrectly assume is a date, you're making life better for everybody.