Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Seems pretty good. Specifically this part of the guide is pretty well written: https://cloud.google.com/apis/design/resources. One thing that is surprising to me however is that their is no mention of using HTTP Status Codes in responses.


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.


Our 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).


HTTP 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.


Thank 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 :)


Context: 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?


The 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.


Yes, an additional 4xx code to help differentiate between api endpoints and resources would be nice.

I didn't mean to imply that HTTP status codes could stand alone as error messages, so for a 404 error I'd also respond with more data, to help the user identify the issue.


Yeah.. The bigger issue with this app is that it responds with a default apache 404 page instead of a 404 code + its usual xml response.


I think that this example illustrates why parent mentioned that this is a trap.


I mean, if the API endpoint is renamed, they have broken all their clients.


That 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.


You 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.


> 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.


What about status=ok|error[|partial]? how do you feel about this? Given its value you may have either result or errors attribute.


Thanks for the comment. The error handling chapter will be published in a few weeks. For now, you can reference https://github.com/googleapis/googleapis/blob/master/google/....

Disclaimer: I am one of the co-authors.


Canonical error codes used by Google, mapped to HTTP error codes: https://github.com/googleapis/googleapis/blob/master/google/...


Well, I can tell you from using their API's that Google doesn't necessarily use them.

I don't recall that specific scenarios, but over the past year I learned this with the maps API. As long as you're hitting a real endpoint, then it will return 200 - even when there are errors and it should clearly return a matching http status code.

I suppose it so the same API could be implemented in any given protocol, however, I don't think that is useful in many cases.


Many Google APIs were created before this guide. New APIs published at https://github.com/googleapis follow this guide. Having the same API available via both REST and gRPC is very valuable, as gRPC often provides 10x performance.


You might have been hitting the old JSON-RPC endpoint of that API, which has to return 200 to follow the standard. Or a gRPC version if there's one already.

Otherwise HTTP status codes for errors are used, and standardized internally.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: