-
Notifications
You must be signed in to change notification settings - Fork 10.4k
[release/6.0] HTTP/3: Support canceling requests that aren't reading a body #35823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,6 +124,30 @@ public void Initialize(Http3StreamContext context) | |
} | ||
|
||
_frameWriter.Reset(context.Transport.Output, context.ConnectionId); | ||
|
||
// We register to connection closed to handle situation where the client | ||
// aborts after data is already sent. Only its read-side of the stream is aborted | ||
// which means Kestrel is only notified of the abort when it writes to the stream. | ||
// This event immediately notifies Kestrel that the client has aborted the request | ||
// and Kestrel will complete pipes and cancel the RequestAborted token. | ||
// | ||
// TODO: Consider a better way to provide this notification. For perf we want to | ||
// make the ConnectionClosed CTS pay-for-play, and change this event to use | ||
// something that is more lightweight than a CTS. | ||
Comment on lines
+134
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be created lazily from the RequestAborted property? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we still want to stop and complete the output pipes in this situation. So, we always want this event raised, even if someone hasn't subscribed to RequestAborted. |
||
context.StreamContext.ConnectionClosed.Register(static s => | ||
{ | ||
var stream = (Http3Stream)s!; | ||
|
||
if (!stream.IsCompleted) | ||
{ | ||
// An error code value other than -1 indicates a value was set and the request didn't gracefully complete. | ||
var errorCode = stream._errorCodeFeature.Error; | ||
if (errorCode >= 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does an error code of 0 indicate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It means the stream was aborted with error code of 0. That doesn't have any meaning in HTTP/3, but it's a valid error code for QUIC. |
||
{ | ||
stream.Abort(new ConnectionAbortedException(CoreStrings.Http2StreamResetByClient), (Http3ErrorCode)errorCode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be updated to call |
||
} | ||
} | ||
}, this); | ||
} | ||
|
||
public void InitializeWithExistingContext(IDuplexPipe transport) | ||
|
@@ -465,7 +489,9 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli | |
catch (ConnectionResetException ex) | ||
{ | ||
error = ex; | ||
Abort(new ConnectionAbortedException(ex.Message, ex), (Http3ErrorCode)_errorCodeFeature.Error); | ||
|
||
var resolvedErrorCode = _errorCodeFeature.Error >= 0 ? _errorCodeFeature.Error : 0; | ||
Abort(new ConnectionAbortedException(ex.Message, ex), (Http3ErrorCode)resolvedErrorCode); | ||
} | ||
catch (Exception ex) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO
IProtocolErrorCodeFeature.Error
should have been nullable, but the API ship sailed in .NET 5.QUIC and HTTP/3 errors are variable-length integers that are always positive so -1 can be used to represent unset.