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

WinHttpHandler: Read HTTP/2 trailing headers (replacement PR) #48704

Merged
merged 28 commits into from
Mar 10, 2021

Conversation

antonfirsov
Copy link
Member

@antonfirsov antonfirsov commented Feb 24, 2021

Fixes #44778, finalizing the work started in #46602.

Notes from the original PR:

  • Adds netstandard2.1 target.
  • Loads trailers into HttpResponseMessage.TrailingHeaders in netstandard2.1. With older targets the trailers are stashed in HttpRequestMessage.Properties.

Additions to the original PR:

  • Tests have been made conditional to OS Build >=19622
  • Feature detection logic added based on WinHTTP team's recommendation (check for WINHTTP_OPTION_STREAM_ERROR_CODE)
  • Fix WinHttpHandler.Unit.Tests build
  • Some refactor work to keep the code maintainable

Notes on testing

  • Currently, none of the CI machines pass the OS Version condition of the Trailers tests, therefore the only proof that the feature actually works is that the new tests passed locally on VM running a preview Windows build.
  • It's seems impossible to design automatic tests that work with .NET Framework. Framework doesn't support ALPN, rendering LoopbackServer useless. I validated the feature with a local-only test case, testing a feature with a remote endpoint running on localhost. It's not possible to host this service as an Azure App, because Azure can not bypass ISS, and Kestrel does not support Trailers with IIS. This is an unfortunate situation IMO, since we added this feature primarily for .NET Framework gRPC support, and looks like we will never be able to regression test it.

/cc @JamesNK

@ghost
Copy link

ghost commented Feb 24, 2021

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

Issue Details

Fixes #44778, finalizing the work started in #46602.

Notes from the original PR:

  • Adds netstandard2.1 target.
  • Loads trailers into HttpResponseMessage.TrailingHeaders in netstandard2.1. With older targets the trailers are stashed in HttpRequestMessage.Properties.

My additions to the original PR:

  • Tests have been made conditional to OS Build >=19622
  • Feature detection logic added based on WinHTTP team's recommendation (check for WINHTTP_OPTION_STREAM_ERROR_CODE)
  • Fix WinHttpHandler.Unit.Tests build
  • Some refactor work to keep the code maintainable

Notes on testing

  • Currently, none of the CI machines pass the OS Version condition of the Trailer's tests, therefore the only proof that the feature actually works is that the new tests passed locally on VM running a preview Windows build.
  • It's seems impossible to design automatic tests that work with .NET Framework. Framework doesn't support ALPN, rendering LoopbackServer useless. I validated the feature with a local-only test case, testing a feature with a remote endpoint running on localhost. It's not possible to host this service as an Azure App, because it can't bypass ISS, and Kestrel does not support Trailers with IIS. This is an unfortunate situation IMO, since we added this feature primarily for .NET Framework gRPC support, and looks like we will never be able to regression test it.

/cc @JamesNK

Author: antonfirsov
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

@antonfirsov antonfirsov requested a review from a team February 24, 2021 16:23
@antonfirsov
Copy link
Member Author

@JamesNK do you plan to do some sort of end-to-end validation of dotnet/core#5713 or have you already done it with your prototype?

@JamesNK
Copy link
Member

JamesNK commented Feb 24, 2021

I tested end-to-end with my earlier PR.

Once this PR is merged I'll reference WinHttpHandler preview package off the .NET 6 feed and re-run the test.

There is a copy of it here if you want to try it yourself. Replace the WinHttpHandler.dll file in the console's Lib directory.

@JamesNK
Copy link
Member

JamesNK commented Feb 24, 2021

It's seems impossible to design automatic tests that work with .NET Framework.

Is that is a common problem with all WinHttpHandler HTTP/2 tests on .NET Framework?

Kestrel does not support Trailers with IIS

It does with .NET 5 + Windows 10 Build 20241 or later.

Comment on lines 242 to 256
if (!isTrailingHeaders)
{
Debug.Assert(lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND);

if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER)
if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER)
{
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
}
}
else
{
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
if (!(lastError == Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER || lastError == Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND))
{
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
}
Copy link
Member

Choose a reason for hiding this comment

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

Seems like this would be simpler as:

if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER &&
    (!isTrailingHeaders ||
     lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND))
{
    throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
}

or something like that?

Copy link
Member Author

@antonfirsov antonfirsov Feb 25, 2021

Choose a reason for hiding this comment

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

It also has to be preceded by:

Debug.Assert(isTrailingHeaders || lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND);

Can't decide if the code more readable in this form, pushed a change anyways.

@antonfirsov
Copy link
Member Author

antonfirsov commented Feb 25, 2021

Is that is a common problem with all WinHttpHandler HTTP/2 tests on .NET Framework?

@JamesNK yes, I think it's a big gap, the following is a very common pattern to disable tests here:

public async Task GetAsync_IPv6LinkLocalAddressUri_Success()
{
if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value)
{
return;
}

The only way to overcome this is to use our shared remote endpoints (stuff under https://corefx-net-http2.azurewebsites.net/) instead of LoopbackServer.

Kestrel does not support Trailers with IIS
It does with .NET 5 + Windows 10 Build 20241 or later.

Don't have much experience with Azure App Services, creating a website with a preview Windows build doesn't look like a trivial task to me. So I think we are stuck with local testing for now.

@antonfirsov
Copy link
Member Author

There is an issue we need to look at before proceeding. Might be a local config issue or a bug in the Windows preview build I'm using (21320), but I'm concerned if it's something more serious.

On my preview test machine, running TrailingHeadersTests separately works, but running the whole tests suite together makes them fail with an exception coming from SslStream, also resulting in a bunch of other SSL failures which may be related:
https://gistpreview.github.io/?8c44cb205e96e698a0999d7cd7666a27

This is also happening with the original #46602 branch.

@JamesNK have you seen this on your preview test machine? @wfurt do those error messages ring any bells?

@JamesNK
Copy link
Member

JamesNK commented Feb 25, 2021

I don’t know.

It took me a while to setup the runtime solution and tests, I focused on just getting the new trailers tests working.

Base automatically changed from master to main March 1, 2021 09:08
@antonfirsov

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

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.

Outstanding test failures look unrelated. Confirm they're unrelated or fix.

HTTP/2 trailers changes LGTM.

@antonfirsov

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

Copy link
Contributor

@alnikola alnikola left a comment

Choose a reason for hiding this comment

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

LGTM

@JamesNK
Copy link
Member

JamesNK commented Mar 9, 2021

FYI

@antonfirsov
Copy link
Member Author

Outerloop test failures are unrelated: #40798 #44015 (comment) #45774 #40798 #1479 #43931

I'm merging this finally.

@antonfirsov
Copy link
Member Author

antonfirsov commented Mar 10, 2021

FYI opened tracking issue to document the feature:
dotnet/dotnet-api-docs#5404

@ghost ghost locked as resolved and limited conversation to collaborators Apr 9, 2021
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.

WinHttpHandler HTTP/2 trailing headers
5 participants