Skip to content

Conversation

@adityamandaleeka
Copy link
Member

@adityamandaleeka adityamandaleeka commented Aug 6, 2024

Optionally respect HTTP/1.0 keep-Alive for HTTP.sys

#56558 was done in 9.0 and made it so we respect keep-alives from 1.0 clients in HTTP.sys. This effectively backports that logic to 8.0 but in an opt-in way (behind an AppContext switch).

Description

This change adds an AppContext switch that, when enabled (it's off by default), will allow our HTTP.sys server to respect HTTP/1.0 clients' Connection: Keep-Alive header.

Fixes #56223

Customer Impact

With this change, servers that serve HTTP/1.0 clients can opt in to respecting the keep-alive header, and thereby save on the fixed costs of connection set up/teardown. For situations where there is a significant amount of 1.0 traffic, this can lead to significant cost savings.

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

This behavior is opt-in behind an AppContext switch.

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

@ghost ghost added the area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions label Aug 6, 2024
@dotnet-policy-service dotnet-policy-service bot added this to the 8.0.x milestone Aug 6, 2024
public async Task ResponseHeaders_HTTP10KeepAliveRequest_Gets11Close()
public async Task ResponseHeaders_HTTP10KeepAliveRequest_KeepAliveHeader_RespectsSwitch()
{
AppContext.SetSwitch("Microsoft.AspNetCore.Server.HttpSys.RespectHttp10KeepAlive", true);
Copy link
Member

Choose a reason for hiding this comment

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

I remember there being some complexity here around interactions between different tests. That is, if tests are running in parallel, I don't think we want this changing states. I'm pretty sure Chris suggested I create an internal property populated from the context switch but overridable by tests.

Copy link
Member

Choose a reason for hiding this comment

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

See KestrelServerOptions.FinOnError.

Copy link
Contributor

@mgravell mgravell Aug 6, 2024

Choose a reason for hiding this comment

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

for EnableKernelResponseBuffering, I made use of an internal property on HttpSysOptions, that is initialized in the .ctor via the app-context switch - that way, relevant tests can set it explicitly via the internal property rather than the app-context switch (IVTA is already in place)

but yes @amcasey you're right that changing app-context directly in tests makes for a race condition in parallel tests - and also if this one test fails and exits prematurely, it might never be set back to the false state, which could cause additional behaviour changes, make finding the real cause difficult

private string? _requestQueueName;

private const string RespectHttp10KeepAliveSwitch = "Microsoft.AspNetCore.Server.HttpSys.RespectHttp10KeepAlive";
internal bool RespectHttp10KeepAlive = AppContext.TryGetSwitch(RespectHttp10KeepAliveSwitch, out var enabled) && enabled;
Copy link
Member

Choose a reason for hiding this comment

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

I might say "// Internal for testing".

@dotnet dotnet deleted a comment from github-actions bot Aug 7, 2024
@dotnet dotnet deleted a comment from github-actions bot Aug 7, 2024
@dotnet dotnet deleted a comment from github-actions bot Aug 7, 2024
@adityamandaleeka adityamandaleeka added the Servicing-consider Shiproom approval is required for the issue label Aug 8, 2024
// HTTP/1.0 clients upon receipt of a Keep-Alive connection token.
// However, a persistent connection with an HTTP/1.0 client cannot make
// use of the chunked transfer-coding. From: https://www.rfc-editor.org/rfc/rfc2068#section-19.7.1
keepConnectionAlive = _respectHttp10KeepAlive && requestConnectionKeepAliveSet && !responseChunkedSet;
Copy link
Member

@Tratcher Tratcher Aug 8, 2024

Choose a reason for hiding this comment

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

responseChunkedSet is only for cases where the application sets the chunked header and does the chunking themselves, it doesn't cover the default case where the server does chunking automatically. See _boundaryType = BoundaryType.Chunked; vs _boundaryType = BoundaryType.PassThrough; below.

edit nevermind, the automatic case only happens for 1.1.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the review!

@adityamandaleeka adityamandaleeka added Servicing-approved Shiproom has approved the issue and removed Servicing-consider Shiproom approval is required for the issue labels Aug 10, 2024
@wtgodbe wtgodbe merged commit f85f009 into dotnet:release/8.0 Aug 12, 2024
@dotnet-policy-service dotnet-policy-service bot modified the milestones: 8.0.x, 8.0.9 Aug 12, 2024
@rbhanda rbhanda modified the milestones: 8.0.9, 8.0.10 Oct 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions Servicing-approved Shiproom has approved the issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants