One of the most salient features of our Tech Hiring culture is that there is so much bullshit. Everyone knows this. Each of us contributes his share. But we tend to take the situation for granted.
One of the most salient features of our Tech Hiring culture is that there is so much bullshit. Everyone knows this. Each of us contributes his share. But we tend to take the situation for granted.
If you are doing REST, you can ignore my snarky comment and read the fine article instead.
For GraphQL specifically, Facebook took the somewhat controversial decision to throw away all HTTP codes and verbs and server-side caching mechanisms. Everything is a POST { "query": "graphql query", variables: { json } } to example.com/graphql and returns HTTP 200 OK. Exceptions and failures are treated via another mechanism. Caching... who needs caching?
Thanks for sharing this @jmfayard, I have only worked with REST APIs, so this is mostly about it, but I am glad that now the readers can understand the context for GraphQL from your comment as well.
Tech Lead/Team Lead. Senior WebDev.
Intermediate Grade on Computer Systems-
High Grade on Web Application Development-
MBA (+Marketing+HHRR).
Studied a bit of law, economics and design
Location
Spain
Education
Higher Level Education Certificate on Web Application Development
@jmfayard isn't a world without errors the one we want? π
At the end is a design decision and you can use it or not. Apollo sure has some errors available. Got your point anyway π
Assuming that /users is the resource used even when doing a GET /users?name=sam, and obtaining a 404 HTTP status code makes no sense because the resource /users exists
Tech Lead/Team Lead. Senior WebDev.
Intermediate Grade on Computer Systems-
High Grade on Web Application Development-
MBA (+Marketing+HHRR).
Studied a bit of law, economics and design
Location
Spain
Education
Higher Level Education Certificate on Web Application Development
Plus using /users?name=sam you're seeking for a given resource (a user who's name is sam) and if there is none, then the resource could not be found, hence the 404 - Not Found.
On the other hand, if you request for /users I totally agree on receiving an empty array as response.
Smiling person, father of two, Husband, Senior Developer/Architect (in that exact order, it's important)
Experience in development since 2004
Linux user and advocate since 2001
Mostly because it depends on what you do, and who uses your API.
When working on an REST server, I would say that everything you said is OK.
But, you could also consider that http code were not designed for this. So any implementation could be ok.
I would say that http codes are simply things of an other era from the beginning of internet.
When using a rest server, the only thing that matters is the error codes you returns.
So for my point of view, as long as you define a pattern such as:
the end point doesn't exist: 404
the server cannot handle what you sent, because you send an XML and the server handles Jason only. => 400
everything else could be a 200
you are creating/updating/deleting a resource (when you talked about using 204), return a simple "ok:true" or "acknowledged:true"
the password cannot be accepted => 200 + error code about password that cannot be accepted
you search something that do not exist => 200
Someone is consuming your API, the way some libraries are working lead to problems when the server returns something else than a 2XX. I'm thinking about JavaScript here. You can count on developers to handle the success, but not the errors. It will lead to JavaScript app that will stale because they didn't handle the fact that you may return the fact the password can be unaccepted.
Also please consider that Google Chrome or Firefox will report non 2xx as errors. Some of your clients may report you this as a problem because they appear in red in the console.
People will have to handle the errors you return. I18n matters.
Http codes won't be enough, so I would say the only thing that matters is the error code you return.
Someone is consuming your API, the way some libraries are working lead to problems when the server returns something else than a 2XX. I'm thinking about JavaScript here. You can count on developers to handle the success, but not the errors. It will lead to JavaScript app that will stale because they didn't handle the fact that you may return the fact the password can be unaccepted.
I can claim the opposite: a poorly written library won't handle the response correctly and will just look at the response status code. Have fun debugging that. The response claims everything is okay, the error won't pop out on you in HTTP logs, and the client library may end up passing garbage data to your application (think of all the times dealing with "Cannot read properties of undefined" error).
In fact, JavaScript's fetch will fail only due to network error, it won't throw on 4xx or 5xx status codes. If you are opting into a wrapper library which treats different status codes as errors, maybe you should also opt into a correct error handling.
Personally, I don't see status codes as a relic of the past, but as a useful tool for handling common situations in API communication. Sure, status codes don't handle all the scenarios by themselves, but there you can use a detailed response. There's even RFC 7807 suggesting a standardized format for errors in HTTP APIs.
Anyway, no matter how you approach HTTP status codes in your API, just make sure to properly document the error responses. It will save your users a lot of pain.
Smiling person, father of two, Husband, Senior Developer/Architect (in that exact order, it's important)
Experience in development since 2004
Linux user and advocate since 2001
Ohh, great article! I donβt know how many times Iβve discussed whether to use 401 or 403. itβs really helpful, to look into the specs. Especially that part that says βyou must not retry the request unalteredβ in some cases helps to understand whether or to use one or the other.
Also, returning 404 instead of 403 make sense, this is definitely something I have learned today.
Regarding the 422, it makes sense but I have never seen any API in the wild that actually uses that. I would think that most 400 responses should actually be 422 according to the specs.
Your definition of error 400 is outdated, it corresponds to the RFC 2616 (1999) which was replaced by RFC 7231 (2014) then RFC 9110 (2022) which defines error 400 as follows :
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).
Based on this definition, a 400 is perfectly acceptable in the case of a well-formed request body containing an unacceptable value. Furthermore, error 422 is basically adapted to the WebDav context (although this no longer seems to be the case in RFC 9110)
I use HTTP 200 everywhere because Facebook says it's the best practice now #graphql
eeew
Source please?
If you are doing REST, you can ignore my snarky comment and read the fine article instead.
For GraphQL specifically, Facebook took the somewhat controversial decision to throw away all HTTP codes and verbs and server-side caching mechanisms. Everything is a
POST { "query": "graphql query", variables: { json } }to example.com/graphql and returnsHTTP 200 OK. Exceptions and failures are treated via another mechanism. Caching... who needs caching?See for example 200 OK! Error Handling in GraphQL and serving GraphQL over HTTP
Thanks for sharing this @jmfayard, I have only worked with REST APIs, so this is mostly about it, but I am glad that now the readers can understand the context for GraphQL from your comment as well.
@jmfayard isn't a world without errors the one we want? π
At the end is a design decision and you can use it or not. Apollo sure has some errors available. Got your point anyway π
Hello Pragati Verma,
thank you for your article.
It's easy to read and the examples you give are easy to understand.
Thank you. I am glad that you liked it :D
Great share! π―
@pragativerma18
Thank you. I am glad that you liked it π
Some people argue that query is part of the resource: en.wikipedia.org/wiki/URL
Plus using
/users?name=samyou're seeking for a given resource (a user who's name is sam) and if there is none, then the resource could not be found, hence the 404 - Not Found.On the other hand, if you request for
/usersI totally agree on receiving an empty array as response.Your article is good.
It shows a way to consider http code.
Unfortunately, it's very complicated π
Mostly because it depends on what you do, and who uses your API.
When working on an REST server, I would say that everything you said is OK.
But, you could also consider that http code were not designed for this. So any implementation could be ok.
I would say that http codes are simply things of an other era from the beginning of internet.
When using a rest server, the only thing that matters is the error codes you returns.
So for my point of view, as long as you define a pattern such as:
Someone is consuming your API, the way some libraries are working lead to problems when the server returns something else than a 2XX. I'm thinking about JavaScript here. You can count on developers to handle the success, but not the errors. It will lead to JavaScript app that will stale because they didn't handle the fact that you may return the fact the password can be unaccepted.
Also please consider that Google Chrome or Firefox will report non 2xx as errors. Some of your clients may report you this as a problem because they appear in red in the console.
People will have to handle the errors you return. I18n matters.
Http codes won't be enough, so I would say the only thing that matters is the error code you return.
I can claim the opposite: a poorly written library won't handle the response correctly and will just look at the response status code. Have fun debugging that. The response claims everything is okay, the error won't pop out on you in HTTP logs, and the client library may end up passing garbage data to your application (think of all the times dealing with "Cannot read properties of undefined" error).
In fact, JavaScript's
fetchwill fail only due to network error, it won't throw on4xxor5xxstatus codes. If you are opting into a wrapper library which treats different status codes as errors, maybe you should also opt into a correct error handling.Personally, I don't see status codes as a relic of the past, but as a useful tool for handling common situations in API communication. Sure, status codes don't handle all the scenarios by themselves, but there you can use a detailed response. There's even RFC 7807 suggesting a standardized format for errors in HTTP APIs.
Anyway, no matter how you approach HTTP status codes in your API, just make sure to properly document the error responses. It will save your users a lot of pain.
I concede. I'm not using JavaScript, I only know developers who does. And I know they faced problems few years ago because of that.
Thanks for sharing the rfc, I will read it.
Once again, http codes can be considered in multiple ways. None is invalid.
Facebook move to almost always send 200 is not stupid. It's a choice.
Http codes as error codes are only a convention between who consumes your API and you. Everything is vid as long it's documented.
I will read the rfc you mentioned, thanks for sharing
Ohh, great article! I donβt know how many times Iβve discussed whether to use 401 or 403. itβs really helpful, to look into the specs. Especially that part that says βyou must not retry the request unalteredβ in some cases helps to understand whether or to use one or the other.
Also, returning 404 instead of 403 make sense, this is definitely something I have learned today.
Regarding the 422, it makes sense but I have never seen any API in the wild that actually uses that. I would think that most 400 responses should actually be 422 according to the specs.
Your definition of error 400 is outdated, it corresponds to the RFC 2616 (1999) which was replaced by RFC 7231 (2014) then RFC 9110 (2022) which defines error 400 as follows :
Based on this definition, a 400 is perfectly acceptable in the case of a well-formed request body containing an unacceptable value. Furthermore, error 422 is basically adapted to the WebDav context (although this no longer seems to be the case in RFC 9110)
Exactly what I was looking for πππΎ
500 for everything , except when its 200, effectively a bool
I'm kidding, its sarcasm.