You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some implementations of HTTP/2-compliant servers may set an upper limit on the cumulative number of requests per connection. When a request exceeding this limit is sent, a GOAWAY frame is sent from the server. The GOAWAY frame containsLast-Stream-ID, and streams with IDs lower than the last stream id will continue until completion, but streams with IDs higher than the last stream id will be canceled if the client has already sent one. Canceled requests appear as an exception in YetAnotherHttpHandler.
According to RFC 9113, these canceled streams can be safely retried on a new connection. However, according to hyperium/hyper#2500, hyper has already dropped the information necessary for retries when it receives GOAWAY and cannot automatically retry them. It says that it must be retried at a higher layer.
Possible Solutions
Retry at the YetAnotherHttpHandler layer.
It may be difficult to hold the information necessary to retry until the completion of the request.
Retry at the user code layer.
Currently, the exception doesn't tell us whether the request can be safely retried.
Reproduction
Unfortunately, I was not able to find a way to reproduce this behavior in ASP.NET Core, but was able to reproduce it with NGINX instead.
Enable HTTP/2 in nginx.conf and set the keepalive_requests value to a smaller value such as 10.
If you send more requests than keepalive_requests in a row with YetAnotherHttpHandler, an exception will be thrown.
[Fact]publicasyncTaskGracefulShutdownRetryability(){usingvarhttpClient=newHttpClient(newYetAnotherHttpHandler(){SkipCertificateVerification=true},true);// Warms up the connection// Before the first connection is established and pooled, multiple requests may create multiple connections.{varrequest=newHttpRequestMessage(HttpMethod.Get,$"https://localhost/");awaithttpClient.SendAsync(request);}List<Task>tasks=new();for(vari=0;i<20;i++)// send more than keepalive_requests{varrequest=newHttpRequestMessage(HttpMethod.Get,$"https://localhost/");tasks.Add(httpClient.SendAsync(request));}varex=awaitRecord.ExceptionAsync(async()=>awaitTask.WhenAll(tasks));testOutputHelper.WriteLine(ex?.ToString()??"no error");Assert.IsType<HttpRequestException>(ex);}
The text was updated successfully, but these errors were encountered:
Some implementations of HTTP/2-compliant servers may set an upper limit on the cumulative number of requests per connection. When a request exceeding this limit is sent, a GOAWAY frame is sent from the server. The GOAWAY frame contains
Last-Stream-ID
, and streams with IDs lower than the last stream id will continue until completion, but streams with IDs higher than the last stream id will be canceled if the client has already sent one. Canceled requests appear as an exception in YetAnotherHttpHandler.According to RFC 9113, these canceled streams can be safely retried on a new connection. However, according to hyperium/hyper#2500, hyper has already dropped the information necessary for retries when it receives GOAWAY and cannot automatically retry them. It says that it must be retried at a higher layer.
Possible Solutions
Reproduction
Unfortunately, I was not able to find a way to reproduce this behavior in ASP.NET Core, but was able to reproduce it with NGINX instead.
Enable HTTP/2 in nginx.conf and set the
keepalive_requests
value to a smaller value such as10
.If you send more requests than
keepalive_requests
in a row with YetAnotherHttpHandler, an exception will be thrown.The text was updated successfully, but these errors were encountered: