Hacker News new | ask | show | jobs
by grandalf 3232 days ago
> It's possible there is nothing between the OS handling TCP and your application.

This does happen, and it results in the client having to have ad-hoc code to deal with a nearly infinite number of possible "Server error" scenarios, some of which may be normal functions of the API and others which may actually be server failures.

> It's possible there is nothing between the OS handling TCP and your application.

I'm not arguing that one shouldn't use HTTP status codes, I'm arguing that they should be used only for the standard meaning of the code, one should not need to consult a table provided by the API designer to determine which 4xx HTTP status codes warrant a retry, and which 5xx status codes are normal vs exceptional situations.

Suppose you make a call to an API and it returns 5xx because you provided a parameter value that is valid in the URL or payload but invalid in the app (suppose your app doesn't allow usernames that are profane words, for example). The response should not be 5xx, it should be 2xx with a message indicating the application's preferred range of values. 5xx means that something went wrong on the server trying to fulfill the request, 2xx means that the request was fulfilled properly, and any additional info relevant to the client should be passed along as part of that 200 response.

> This is also against the concept of REST

Very few APIs can be designed well as 100% REST. Lots of very typical scenarios necessitate jumping through a lot of hoops to use REST in a pure way. REST fights with database normalization in some cases and with many authentication scenarios. It can also require the client to maintain a fairly elaborate (and brittle) representation of server-side state that is mostly unnecessary.

REST makes sense when there is a perfect alignment between REST verbs and data flows, but when you get into a situation where it's necessary to make multiple API calls to do one logical operation, it would probably have been simpler not to use REST in the first place and to have just designed a simple, clean, non-REST API.

1 comments

> Suppose you make a call to an API and it returns 5xx because you provided a parameter value that is valid in the URL or payload but invalid in the app

That is wrong. Client mistakes should get 400-level error codes. A 200-level code indicates the request completed successfully, which it didn't.

There is no difference between an "HTTP server" and an app. They are often the same thing, like when using Apache to serve files from disk.

> I'm not arguing that one shouldn't use HTTP status codes, I'm arguing that they should be used only for the standard meaning of the code

Of course you should use the error codes correctly! Don't return a 200 code when the request failed.

> Don't return a 200 code when the request failed.

The request didn't fail, it simply followed application logic and returned a successful response indicating the nature of the application logic to the client. That is not an error condition, it's just application logic.

And said logic determined your input was invalid, HTTP 400 Bad Request is a perfectly reasonable response.

If you want to use HTTP as nothing more than a transport layer and return 200 OK's all day then fine, but why are you even using HTTP at that point?

Unless I'm doing some sort of pure REST API I'm simply using HTTP as a transport protocol for my application specific protocol.

If HTTP delivers my application protocol's message successfully, it's an HTTP 2xx, but my application's protocol may have a range of statuses that are not "transport-like" in the way HTTP status codes are, which are the main things that API consumers care about, assuming the basic transport is working.

Every web server I've ever used returns a 500 server error when the transport succeeds but it encounters an exception in application level code. Are you really proposing that's incorrect behavior? I also can't imaging a use for 403 Forbidden and 401 Unauthorized that isn't "application level" logic.

If you think about it pretty much 99% of requests the server receives could be correct if the "application logic" was implemented differently. You can't really decouple the two in any meaningful way.

If you want to return 200 OK status codes all day when why are you using HTTP in the first place?

(Also, HTTP is an application protocol)

So then if my application logic catches a thrown exception because I don't want my app to crash every time a server bug is exposed, I should be returning a 200 OK response rather than a 500 Internal Server Error, because the app logic accounts for handling exceptions and returns a response.

I can't disagree more. It just seems like clients would have a nightmare of a time debugging client-side code against such a system.

If it was an error you expected, then you should handle it using application logic. If you use a programming language with exceptions and one gets thrown and you use it for flow control, that doesn't mean the sever is broken.

The API consumer doesn't need to think there is a problem, since you might have ways of handling it in a more subtle way. Maybe when your DB connection times out you send an application specific message that includes the number of milliseconds to wait for a retry. You don't have to let the shit hit the fan and return a 5xx any time something slightly exceptional occurs, 5xx is for things that are truly exceptional and for which you have no helpful information for the consumer about what to do.