-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Description
Under very specific conditions, SocketsHttpHandler.SendAsync when using HTTP/2 attempts to copy the HttpRequestMessage.Content twice.
In Island Gateway (AKA what eventually became YARP), we have code similar to the following, and this invariant that we do a best-effort check is being violated:
The following criteria seem to be necessary to trigger this bug, though it may be broader than this:
- Request specifies
Expect: 100-continue
- Destination does not produce a
100
response within the first 1 second - HttpConnectionPool.SendWithRetryAsync decides to retry (just a hypothesis)
It seems like the SocketsHttpHandler machinery may be deciding it is safe to retry because the destination service provably did not start processing the first attempt, but it seems to make the wrong assumption that it is okay to read the HttpRequestMessage.Content again on the next attempt. This is not a valid assumption, and leads to issues in applications such as YARP where the Content is a wrapper around Kestrel's incoming request body stream, which cannot be read twice.
Configuration
- .NET Core 3.1.15
- Windows Server Datacenter 2019
Other information
Filing this as a result of an offline discussion with @halter73 and @davidfowl. Thanks folks for helping investigate.
@karelz FYI.