Hacker News new | ask | show | jobs
by marrs 3237 days ago

    Many developers use 4xx status codes to indicate things
    like data validation errors or other things that are not
    part of the HTTP transport.
You mean like a form validation error? Surely an invalid request is a bad request. No?
2 comments

agreed... especially because it is an error and if i return a 2xx then the frontend code will then have error logic in the success logic why have two checks when i can have one..
> Surely an invalid request is a bad request.

Invalid to whom? Should a form submitted with a username that already exists in the system get a 500 response code? What's the server error?

I'd go with 409 Conflict, but I'd also accept 400 Bad Request

Incidentally, the RFC for 409 makes it quite clear that this touches the application layer:

> Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the representation being PUT included changes to a resource that conflict with those made by an earlier (third-party) request, the origin server might use a 409 response to indicate that it can't complete the request. In this case, the response representation would likely contain information useful for merging the differences based on the revision history.

https://tools.ietf.org/html/rfc7231#section-6.5.8

In any case, getting pedantic about what's "an error" and using 200 OK for everything that didn't fail at the transport layer is a super frustrating experience regardless of whether or not it's semantically correct. Please don't do that to consumers of your API.

Versioning a resource, per WebDAV is a very specific application.

> using 200 OK for everything that didn't fail at the transport layer is a super frustrating experience regardless of whether or not it's semantically correct

The semantics of my application's protocol do not necessarily mirror the semantics of HTTP, nor are the descriptive statuses semantically similar, since most HTTP statuses are simply about transport (even though a few touch on the "application" of URIs as resources).

Transport layer to me means TCP/IP. HTTP sits above that, in the application domain. If a user sends an invalid request then the response should be in the 400 band. If the server failed in some way to deal with the request (e.g. the database is unavailable), then the response should be in the 500 band.

I would typically decide what my response code should be depending on what I think the response should be.

If a user tries to register a new account then a successful outcome would probably be a new user resource. If the user tries to register a username that already exists, I'd also probably go with 409 Conflict as the user is trying to create a resource that already exists.

There's no mention of WebDAV in that RFC.

Would it kill you to send back a 400 status code upon an error? Having to check for { isError: true } or something similar is obnoxious. I don't see the value gain of responding 200 OK when the operation was not successful.

> when the operation was not successful.

Well, do you care about all the successful and unsuccessful aspects of TCP that underlie the connection? No, you just care that it was successful, allowing the HTTP request. Assuming that is successful, then your API "operation" can occur and return its result.

Some APIs I've seen just use 400 for all generic client-side errors, including request syntax errors, impossible requests, duplicate requests, etc.

I would argue that most of the time, for any sufficiently large application, you'll need to use application specific status codes anyway (as you said), so why bother trying to be specific with the HTTP error codes? Certain client-side applications parse out if the response is a 2xx, 3xx, 4xx, or 5xx, and log it differently. At which point you just need one of them to trigger the different logging behavior.

The only special case I can think of is 401, which you need to send to trigger the basic authentication pop-up window for most browsers.

Exactly.
You could use 422.
422 is from the WebDAV spec, which is not HTTP.

A big portion of the improper overloading of HTTP status codes comes from WebDAV status codes seeming appealing when in fact WebDAV is a very specific set of functionality that is not really analogous to the way most REST APIs work... notably WebDAV offers locking semantics.

> WebDAV spec, which is not HTTP

HTTP is not a closed protocol. There will never be a single document defining all HTTP methods, status codes and such. Nothing in the definition of status code 422 makes it inapplicable to non-WebDAV applications. It is as much standard HTTP as status code 400 is (both are “proposed standards” in IETF terms).

> HTTP is not a closed protocol.

I'm not arguing it is, it's an extension that adds specific semantics to accomplish a specific purpose.

But some developers look at WebDAV and see a lot of similarity with some of the application specific error conditions they are working with and decide that overloading HTTP status codes is a good idea, when it rarely is.

Here’s the standard for 422: https://tools.ietf.org/html/rfc4918#section-11.2. It’s not a WebDAV-specific error condition. People are right to see the similarity and reuse the status code. This is not “overloading”.