Re: BCP56bis: advice for using status codes in applications

On 2019-01-09 06:34, Mark Nottingham wrote:
> Promoting to a new thread, as suggested.
> 
> I explored the thinking behind this in a blog post a while back:
>    https://www.mnot.net/blog/2017/05/11/status_codes
> 
> Julian, do you disagree with that, or just how it's expressed here?
> ...

Ok, let's look at that blog post first. I just re-read it twice, and it 
isn't as far-reaching as the text in bcp6bis. For instance:

> Beyond that, it’s a mistake to try to map each part of your application “deeply” into HTTP status codes; in most cases the level of granularity you want to be aiming for is much coarser. When in doubt, it’s OK to use the generic status codes 200 OK, 400 Bad Request and 500 Internal Service Error when there isn’t a better fit.

Note the "when in doubt".

Later:

> So You Want To Create a HTTP Status Code
> 
> If after reading all of that, you still think you need a new status code – it’s something that’s potentially applicable to all resources, it has specific effect on HTTP implementations, there isn’t an existing status code that has that effect, and you’re willing to go through the process, take a look at these guidelines.

So that is specific to new codes, not using the ones we have.

So, no, I don't really disagree with that blog post. But that's what 
bcp56bis says. In particular:

> 4.6. HTTP Status Codes
> 
> The primary function of a HTTP status code is to convey semantics for the benefit of generic HTTP software, not to convey application-specific semantics.

But then RFC 7231 just says "The status-code element is a three-digit 
integer code giving the result of the attempt to understand and satisfy 
the request." - much broader.

I disagree with this narrow definition. HTTP after all is an 
application-level protocol.

> Status codes are often generated or overwritten by intermediaries, as well as server and client implementations. This can happen, for example, when network errors are encountered, a captive portal is present, when an implementation is overloaded, or it thinks it is under attack. As a result, the status code that a server-side application generates and the one that the client software receives often differ.

I think the more likely case is that the request actually did not reach 
the origin server, so one is really dealing with a non-authoritative answer.

> This means that status codes are not a reliable way to carry application-specific signals. Specifying that a particular status code has a specific meaning in the context of an application can have unintended side effects; if that status code is generated by a generic HTTP component can lead clients to believe that the application is in a state that wasn’t intended.

But how likely is that for the more specific codes such as 409 or 422 
(defined for ages, just recently added to the base spec)?

> Instead, applications using HTTP should specify the implications of general classes of responses (e.g., “successful response” for 2xx; “client error” for 4xx and “server error” for 5xx), conveying any application-specific information in the message body and/or HTTP header fields, not the status code. [RFC7807] provides one way for applications using HTTP to do so for error conditions.

This sounds like intermediaries can break the status code, but for some 
reason can't break the payload.

(I like adding details to the payload, as per RFC 4918 which IMHO did 
that first, and later RFC 7807, but that does not necessarily imply that 
more specific status codes do not make sense as well)

> There are limited exceptions to this; for example, applications might use 201 (Created) or 404 (Not Found) to convey application semantics that are compatible with the generic HTTP semantics of those status codes. In general, though, applications should resist the temptation to map their semantics into fine-grained status codes.

I think using fine-grained status codes actually does no harm, except 
when developers get carried away with that. Thus the "in doubt" in the 
blog post makes sense.

> Because the set of registered HTTP status codes can expand, applications using HTTP should explicitly point out that clients ought to be able to handle all applicable status codes gracefully (i.e., falling back to the generic n00 semantics of a given status code; e.g., 499 can be safely handled as 400 by clients that don’t recognise it). This is preferable to creating a “laundry list” of potential status codes, since such a list is never complete.

+1 (except for the nit about completeness)

> Applications using HTTP MUST NOT re-specify the semantics of HTTP status codes, even if it is only by copying their definition. They MUST NOT require specific reason phrases to be used; the reason phrase has no function in HTTP, is not guaranteed to be preserved by implementations, and the reason phrase is not carried at all in the HTTP/2 [RFC7540] message format.

+1

> Applications MUST only use registered HTTP status codes. As with methods, new HTTP status codes are rare, and required (by [I-D.ietf-httpbis-semantics]) to be registered with IETF Review. Similarly, HTTP status codes are generic; they are required (by [I-D.ietf-httpbis-semantics]) to be potentially applicable to all resources, not just to those of one application.

+1

> When authors believe that a new status code is required, they are encouraged to engage with the HTTP community early, and document their proposal as a separate HTTP extension, rather than as part of an application’s specification.

+1

I'll finish with two more thoughts:

1) There are limits to using the payload for machine-readable status 
information -- it doesn't work well when the request was GET and is 
supposed to make sense in a generic browser, or when it's the result of 
a classic HTML form POST.

2) Maybe it would worthwhile to discuss the usability of a few concrete 
status codes, such as 403, 409, or 422.

Best regards, Julian

Received on Sunday, 20 January 2019 16:51:49 UTC