4 ms·
Using HTTP status codes in your responses is a trap. It conflates the API transport with the actual semantics of the API. The goal of HTTP error responses is to
by programd 10y ago
Using HTTP status codes in your responses is a trap. It conflates the API transport with the actual semantics of the API. The goal of HTTP error responses is to say that something went wrong in the transport layer. The goal of API error responses is to say that something went wrong in your service. For example, your HTTP REST server may be perfectly fine, but your back end DB may be misbehaving. Having separate API level error responses, for example an explicit field called "error" in your JSON response, I consider to be best practice. Frequently your client needs to know the difference, for example to determine what kind of error to return to the user or what retry strategy to use.
In typical HTTP REST services this transport/API error split makes it really easy to create client code which only needs to check two conditions - if the HTTP response code is 200 or not, and if the error value is set or not. You also don't have to shoehorn your error handling into the very limited set of errors provided by the HTTP protocol.
The other real-world advantage of this is that when you outgrow HTTP as the transport protocol for performance reasons this makes porting the API really easy to, e.g. protobuf RPC, or even raw TCP. The error is already defined as part of the API and you don't need to rewrite all your client code to deal with mapping multiple HTTP response codes to your new transport. It's good future proofing I've seen pay off in a at least a couple of real-world cases.
Bottom line - your server should always return HTTP status 200 and a separate API error response.
There's also a reasonable debate to have about whether non-error responses should also include an explicit "error" field with some default OK value. There may be good reasons to leave it out, e.g. if you want to save bandwidth, but I consider that a fairly insignificant point. For consistency my APIs always return a default OK error field on non-error responses - your mileage may vary.
- aaronblohowiak 10y agoThat is great in theory but it throws out all of the deeply rooted tooling that reports and aggregates http status codes across the service architecture. It is nice to be able to tail the apache log and see the status. In your situation I would need to have an additional system that uses application details for similar purposes.. you can do it as you describe but there is a cost! It is also against convention, which increases the custom tribal knowledge that people working in that system have to acquire. By the time you "outgrow" http I assume you'd have custom metrics and logging/tracing, but I would not suggest it as a good place to start.
- johnjuuljensen 10y agoHTTP has some very useful status codes, which convey standard conditions found in most apis: 200, 201, 400, 401, 404, 403, 406, 429, 500 Also note that not all APIs will be used be developers. Often it's someone less proficient with programming, and you can't rely on them to check the content of the return message. Help them help themselves by making curl (or whatever) bitch when there is an error. It takes a bit more work to design an API that works over multiple transports, but a good framework, such as Servicestack.net if your in .Net land, mostly does it for you. By advocating 200 for all responses you're basically reverting to SOAP and WCF (Windows Communication Foundation). Each to his own though, and for internal stuff, it might make a lot more sense.
- programd 10y agoThank you all for the good responses on the error code issue. I particularly appreciate the ops view on this, e.g. the existence of much tooling around monitoring HTTP codes. Since I'm a pragmatist I'm not going to defend my point of view too vigorously, but concede that there are other considerations, particularly when designing services to work at scale. Everything breaks at scale, including many things we believe to be wise and true :)
- johnjuuljensen 10y agoContext: Friendly banter >> Bottom line - your server should always return HTTP status 200 and a separate API error response. That is a very absolute statement from a pragmatic guy, asking people to concede viewpoints other than their own :) I'd be interested in learning how status codes other than 200 cause problems at scale though?
- justinsaccount 10y agoThe problem with things like 404 is then you need to differentiate between "Hi, this is the application and the object/document/whatever you are looking for was not found" with "Hi, this is the server and the api endpoint was not found" An API I use returns a standard apache 404 error page when the item you are looking up doesn't exist. If the API endpoint was renamed my code that consumes it wouldn't have any idea anything was wrong.
- euyyn 10y agoOur experience, from having gone that route internally and externally (e.g. with JSON-RPC), is that it ends up not paying off to have that separation. From the client side, developers shouldn't need to worry about what piece of your stack was at fault. They want to know if it's your fault or theirs/their user's. And if it's their fault, how to prevent it or fix it. Both HTTP and gRPC are flexible enough to encode that information. From the server side, it complicates monitoring in practice if errors are propagated encoded in the response body of a "successful" RPC. With reverse proxies and other things in place, the complication increases, and many people get unhappy. W.r.t. migrating clients to other transports, the client library should hide that (we haven't done that always right in the past, but we do now).
- orasis 10y agoYou are just plain wrong. HTTP was designed to access and update named resources. Those status codes correspond to the status of that resource so are totally appropriate no matter if the resource is a static HTML file or a database driven JSON response. I would hate to consume your APIs over HTTP.
- eveningcoffee 10y agoWhat about status=ok|error[|partial]? how do you feel about this? Given its value you may have either result or errors attribute.
- paulddraper 10y ago> The goal of HTTP error responses is to say that something went wrong in the transport layer. Huh? What networking model are you working on? HTTP is application layer. TCP is transport layer. IP is internet layer. Ethernet is network layer.