Skip to content

Commit 4b119ec

Browse files
Tratcherguardrex
andauthored
Clarify request draining comments (#18132)
* Clarify request draining comments * Nits Co-authored-by: Luke Latham <1622880+guardrex@users.noreply.github.com>
1 parent cca2859 commit 4b119ec

1 file changed

Lines changed: 14 additions & 12 deletions

File tree

aspnetcore/fundamentals/servers/kestrel.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn about Kestrel, the cross-platform web server for ASP.NET Core
55
monikerRange: '>= aspnetcore-2.1'
66
ms.author: riande
77
ms.custom: mvc
8-
ms.date: 05/03/2020
8+
ms.date: 05/04/2020
99
no-loc: [Blazor, "Identity", "Let's Encrypt", Razor, SignalR]
1010
uid: fundamentals/servers/kestrel
1111
---
@@ -2708,33 +2708,35 @@ Host Filtering Middleware is disabled by default. To enable the middleware, defi
27082708
27092709
::: moniker-end
27102710

2711-
## HTTP connection request draining
2711+
## HTTP/1.1 request draining
27122712

2713-
Opening HTTP connections is relatively demanding on server resources, so Kestrel tries to reuse connections. A request must be fully consumed to be reused. Some requests can't be fully consumed, such as a `POST` requests where the server returns a redirect. In the `POST`-redirect case:
2713+
Opening HTTP connections is time consuming. For HTTPS, it's also resource intensive. Therefore, Kestrel tries to reuse connections per the HTTP/1.1 protocol. A request body must be fully consumed to allow the connection to be reused. The app doesn't always consume the request body, such as a `POST` requests where the server returns a redirect or 404 response. In the `POST`-redirect case:
27142714

27152715
* The client may already have sent part of the `POST` data.
27162716
* The server writes the 301 response.
2717-
* The connection can't be used for a new request because the `POST` data from the previous request hasn't been fully read.
2718-
* Kestrel tries to drain the request. Draining the request means reading and discarding the data waiting to be read without processing the data.
2717+
* The connection can't be used for a new request until the `POST` data from the previous request body has been fully read.
2718+
* Kestrel tries to drain the request body. Draining the request body means reading and discarding the data without processing it.
27192719

2720-
The draining process makes a tradoff between allowing remaining data to be read/discarded and closing the connection without reading remaining data:
2720+
The draining process makes a tradoff between allowing the connection to be reused and the time it takes to drain any remaining data:
27212721

27222722
* Draining has a timeout of five seconds, which isn't configurable.
2723-
* If all of the data specified by the `Content-Length` header hasn't been read before reaching the timeout, the connection is closed.
2723+
* If all of the data specified by the `Content-Length` or `Transfer-Encoding` header hasn't been read before the timeout, the connection is closed.
27242724

27252725
Sometimes you may want to terminate the request immediately, before or after writing the response. For example, clients may have restrictive data caps, so limiting uploaded data might be a priority. In such cases to terminate a request, call [HttpContext.Abort](xref:Microsoft.AspNetCore.Http.HttpContext.Abort%2A) from a controller, Razor Page, or middleware.
27262726

27272727
There are caveats to calling `Abort`:
27282728

2729-
* It's demanding on server resources to close and open TCP connections.
2729+
* Creating new connections can be slow and expensive.
27302730
* There's no guarantee that the client has read the response before the connection closes.
2731-
* Calling `Abort` should be rare and reserved for server error cases, not common errors.
2731+
* Calling `Abort` should be rare and reserved for severe error cases, not common errors.
27322732
* Only call `Abort` when a specific problem needs to be solved. For example, call `Abort` if malicious clients are trying to `POST` data or when there's a bug in client code that causes large or numerous requests.
2733-
* Don't call `Abort` to process ordinary resonses, such as HTTP 404 (Not Found).
2733+
* Don't call `Abort` for common error situations, such as HTTP 404 (Not Found).
27342734

2735-
Calling [HttpResponse.CompleteAsync](xref:Microsoft.AspNetCore.Http.HttpResponse.CompleteAsync%2A) before calling `Abort` ensures that the response has left the server. However, client behavior isn't predictable and can't be directly controlled by the app. Clients may continue to send data after calling `CompleteAsync` and `Abort`.
2735+
Calling [HttpResponse.CompleteAsync](xref:Microsoft.AspNetCore.Http.HttpResponse.CompleteAsync%2A) before calling `Abort` ensures that the server has completed writing the response. However, client behavior isn't predictable and they may not read the response before the connection is aborted.
27362736

2737-
If possible, it's better for clients to utilize the [Expect: 100-continue](https://developer.mozilla.org/docs/Web/HTTP/Status/100) request header so that they wait for the server to respond before starting to send the request body.
2737+
This process is different for HTTP/2 because the protocol supports aborting individual request streams without closing the connection. The five second drain timeout doesn't apply. If there's any unread request body data after completing a response, then the server sends an HTTP/2 RST frame. Additional request body data frames are ignored.
2738+
2739+
If possible, it's better for clients to utilize the [Expect: 100-continue](https://developer.mozilla.org/docs/Web/HTTP/Status/100) request header and wait for the server to respond before starting to send the request body. That gives the client an opportunity to examine the response and abort before sending unneeded data.
27382740

27392741
## Additional resources
27402742

0 commit comments

Comments
 (0)