Laszlo

Hello, I am Laszlo

Software-Engineer, .NET developer

Contact Me

Request Cancellation in ASP.NET Core with HTTP/2

ASP.NET Core allows to create endpoints that receive a cancellation token, such as below:

app.MapGet("/path", async (CancellationToken token) =>
{
});

In this post, I will explore how a server (such as Kestrel) may fire the token to be canceled.

Cooperative Cancellation

There are several reasons why such a token might be canceled. For example, the client may terminate the connection, or the application may shut down. Note that, at the time of writing, a graceful application shutdown does not trigger the token in ASP.NET Core (.NET 10 preview 5).

.NET and the CancellationToken use a cooperative strategy for canceling requests. This means that for cancellation to occur, user code must periodically check the status of the cancellation token and terminate its operation at a safe point. If the user code does not cooperate, the response is still calculated; however, the server might choose not to send the response to the client.

Stream Cancellation

In HTTP/2, a request-response pair is encapsulated by an HTTP/2 stream. Streams are multiplexed through a connection. The HTTP/2 specification allows streams to be terminated due to an error or cancellation, using the RST_STREAM frame. Clients and servers communicate by sending messages on a stream. Messages are enclosed in frames, and each frame has a type—one of which is RST_STREAM.

When a server receives an RST_STREAM frame, it must terminate the corresponding stream. However, communication between the server and client is asynchronous, so a client that sends an RST_STREAM may still receive frames corresponding to the canceled stream. This is especially apparent when the connection spans multiple hops with intermediaries between the endpoints.

Clients and servers may also terminate the connection with an error or gracefully using the GOAWAY frame.

Endpoints, such as browsers, can send RST_STREAM frames when the user clicks the cancel button on a request.

Streams to Features

A server receiving the RST_STREAM frame will change the stream's status to closed. The stream implementation then triggers the cancellation token, which can be handled by user code. ASP.NET Core can be hosted by multiple servers (IIS, Kestrel, HTTP.sys, etc.), and each implementation may differ. Not every server or protocol supports all aspects of a request. For this reason, ASP.NET Core defines features. Each feature is a contract between the server and the application. One of these features is the IHttpRequestLifetimeFeature. When this feature is implemented (typically by the stream implementation), the RequestAborted property provides a cancellation token that fires when the request is aborted and the application should stop processing.

This token can be used directly by the application or combined with other cancellation sources.

Conclusion

Request cancellation in ASP.NET Core over HTTP/2 is a cooperative process between the client, server, and application code. By leveraging features like IHttpRequestLifetimeFeature and properly handling the CancellationToken, applications can respond promptly to aborted requests—whether triggered by user actions or network events. Understanding how HTTP/2 streams and RST_STREAM frames interact with ASP.NET Core's feature system helps developers write more robust, resource-efficient endpoints. Always ensure your code checks for cancellation to provide a responsive and reliable experience for your users.