Proposal: Change H2 RST_STREAM error code on timeout PROTOCOL_ERROR->CANCEL

Scott Mitchell scott_mitchell at apple.com
Tue May 3 01:27:48 UTC 2022


Thanks for the additional details :)

Agreed there is ambiguity in the RFC for error codes, and retryability will require additional context either way (idempotent, safe, ..). Some points to consider:
- PROTOCOL_ERROR is allowed as a “catch all”, but the client can’t differentiate from other “real protocol errors” (e.g. incorrect frame format, sequencing, ..) which generally aren’t retryable.
- CANCEL also doesn’t tell the client “why”, but it is known to be application level (as opposed to a protocol issue)

wdyt? Since there is no “right answer” understood if this is deemed undesirable or too risky.

-Scott

> On May 2, 2022, at 4:14 PM, Maxim Dounin <mdounin at mdounin.ru> wrote:
> 
> Hello!
> 
> On Mon, May 02, 2022 at 08:19:44AM -0700, Scott Mitchell via nginx-devel wrote:
> 
>> Rational is captured in the patch set below (tests also 
>> updated). Please let me know if this is acceptable.
>> 
> 
>> # HG changeset patch
>> # User Scott Mitchell <scott_mitchell at apple.com>
>> # Date 1651280176 25200
>> #      Fri Apr 29 17:56:16 2022 -0700
>> # Node ID ac2a48aa4efb86cd34189dd1b62fe24c5afbab70
>> # Parent  a736a7a613ea6e182ff86fbadcb98bb0f8891c0b
>> H2: RST_STREAM(CANCEL) on timeout instead of PROTOCOL_ERROR
>> 
>> When a timeout occurs this condition maybe temporary and retryable. For example if the network
>> bandwidth is temporarily throttled. If a PROTOCOL_ERROR is returned the client is unlikely to
>> retry due to unknown error conditions. Returning CANCEL provides more context as an application
>> level error that the client is more likely to retry.
>> 
>> diff -r a736a7a613ea -r ac2a48aa4efb src/http/v2/ngx_http_v2.c
>> --- a/src/http/v2/ngx_http_v2.c	Tue Feb 08 17:35:27 2022 +0300
>> +++ b/src/http/v2/ngx_http_v2.c	Fri Apr 29 17:56:16 2022 -0700
>> @@ -4636,7 +4636,7 @@
>> 
>>         if (!stream->out_closed) {
>>             if (ngx_http_v2_send_rst_stream(h2c, node->id,
>> -                                      fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
>> +                                      fc->timedout ? NGX_HTTP_V2_CANCEL
>>                                                    : NGX_HTTP_V2_INTERNAL_ERROR)
>>                 != NGX_OK)
>>             {
> 
> Thanks for the patch.
> 
> The CANCEL error code is defined by RFC 7540 as follows:
> 
>   CANCEL (0x8):  Used by the endpoint to indicate that the stream is no
>      longer needed.
> 
> This does not seem to apply to the timeout case. In contrast, 
> PROTOCOL_ERROR mostly matches the particular error condition (that 
> is, client failed to provide further frames as expected per 
> protocol in a reasonable time), and it is also defined to be a 
> "catch-all" error:
> 
>   PROTOCOL_ERROR (0x1):  The endpoint detected an unspecific protocol
>      error.  This error is for use when a more specific error code is
>      not available.
> 
> As such, PROTOCOL_ERROR looks more appropriate in the particular 
> case from the protocol point of view.
> 
> If the particular error condition is temporary and retry is 
> desired, it is probably something to do per user action, and the 
> particular error code shouldn't matter as long as retry is 
> requested by the user.
> 
> Hope this helps.
> 
> -- 
> Maxim Dounin
> http://mdounin.ru/



More information about the nginx-devel mailing list