Skip to content
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

WinHttp: always read HTTP/2 streams to the end #62870

Merged
merged 3 commits into from
Dec 20, 2021

Conversation

antonfirsov
Copy link
Member

@antonfirsov antonfirsov commented Dec 15, 2021

By it's default behavior, WinHttp stops reading the stream when Content-Length is specified, this prevents us to read the remaining trailers. By opting in into WINHTTP_OPTION_REQUIRE_STREAM_END, WinHttpHandler behavior becomes equivalent of SocketsHttpHandler. Note that this means if the actual data is longer than Content-Length, we will read all the extra data bytes in both handlers, which we probably shouldn't do, but that's a topic we should investigate separately.

I don't fully understand the impact of applying WINHTTP_OPTION_REQUIRE_STREAM_END in HTTP/1.1, so I'm applying it only for HTTP 2.0 requests.

The PR also adds equivalent Content-Length tests for SocketsHttpHandler for consistency.

Fixes #60291

/cc @JamesNK

@ghost
Copy link

ghost commented Dec 15, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

In it's default behavior, WinHttp stops reading the stream when Content-Length is specified, this prevents us to read the remaining trailers. By opting in into WINHTTP_OPTION_REQUIRE_STREAM_END, WinHttpHandler behavior becomes equivalent of SocketsHttpHandler. Note that this means if the actual data is longer than Content-Length, we will read all the extra data bytes in both handlers, which we probably shouldn't do, but that's a topic we should investigate separately.

I don't fully understand the impact of applying WINHTTP_OPTION_REQUIRE_STREAM_END in HTTP/1.1, so I'm applying it only for HTTP 2.0 requests.

The PR also adds equivalent Content-Length tests for SocketsHttpHandler for consistency.

Fixes #60291

Author: antonfirsov
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

@JamesNK
Copy link
Member

JamesNK commented Dec 15, 2021

Stream end is a http2 and http3 concept. I assume it has no impact on http11. Probably worth double checking with winhttp folks.

I would like a unit test of a http2 server returning more content than its content-length defines. We can check what socketshttphandler does, what winhttphandler does today (pre-pr) and what it does after adding this flag.

My experience is in the server side of http, but there we validate the content length and error if doesn’t match the actual content.

Correct me if I’m wrong @Tratcher :)

@Tratcher
Copy link
Member

The HTTP/2 spec says having a Content-Length mismatch the total data frames is a stream level protocol violation and should result in RST. It's worth confirming WinHttp enforces that.

@antonfirsov
Copy link
Member Author

Since this PR is a candidate for our backport process I'd like to stick to the minimal changes necessary to fix #60291. Opened #62906 to track our lack of response Content-Length enforcement, current behavior is described in that issue.

@JamesNK
Copy link
Member

JamesNK commented Dec 16, 2021

Ok! As long as the impact of the setting is understood then I’m fine with looking at content-length separately.

@antonfirsov
Copy link
Member Author

antonfirsov commented Dec 17, 2021

@JamesNK I pushed b4b70f0 to set the option right on the session handle, since the WinHttp team confirmed it doesn't have effect on Http1.1.

If you are fine with the current state, I'm happy to merge this.

@antonfirsov
Copy link
Member Author

/azp run runtime-libraries-coreclr outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@antonfirsov
Copy link
Member Author

Outerloop failures are unrelated: #63008 #63009

@antonfirsov antonfirsov merged commit 3251f00 into dotnet:main Dec 20, 2021
@karelz karelz added this to the 7.0.0 milestone Dec 22, 2021
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(this, "Failed to enable WINHTTP_OPTION_REQUIRE_STREAM_END error code: " + Marshal.GetLastWin32Error());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetEventSource.Info(this, $"Failed to enable WINHTTP_OPTION_REQUIRE_STREAM_END error code: {Marshal.GetLastWin32Error()}");

@antonfirsov
Copy link
Member Author

/backport to release/6.0

@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2022

Started backporting to release/6.0: https://github.com/dotnet/runtime/actions/runs/1654653739

@ghost ghost locked as resolved and limited conversation to collaborators Feb 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Subsequent Grpc calls with WinHttpHandler to an IIS hosted service fail
5 participants