Skip to content

Conversation

@ManickaP
Copy link
Member

@ManickaP ManickaP commented Jul 13, 2020

Behavior:

RequestVersionOrLower -- current behavior.

  • If HTTP/1 and no TLS, use HTTP/1.
  • If HTTP/1 and TLS, use HTTP/1.
  • If HTTP/2 and no TLS, use HTTP/1.
  • If HTTP/2 and TLS, use ALPN to negotiate between HTTP/1 and HTTP/2.

RequestVersionOrHigher -- start at the user's version.

  • If HTTP/1 and no TLS, use HTTP/1.
  • If HTTP/1 and TLS, use ALPN to negotiate between HTTP/1 and HTTP/2.
  • If HTTP/2 and no TLS, use HTTP/2 cleartext (H2C)
  • If HTTP/2 and TLS, use ALPN and fail if server returns error.
    • we leave the original exception as-is now, because we don't know exactly what to look for to be able to map it to a better one

RequestVersionExact -- exactly what the user asked for.

  • If HTTP/1 and no TLS, use HTTP/1.
  • If HTTP/1 and TLS, use HTTP/1.
  • If HTTP/2 and no TLS, use HTTP/2 cleartext (H2C)
  • If HTTP/2 and TLS, use ALPN and fail if server returns error.

Other issues

  • H3 not tested at all yet
  • Loopback servers cannot handle upgrade/downgrade at all. Not as easy as it seams to change. I will probably create a new issue for it. Fixed.
  • No H3 remote server, no H2C remote server.

@scalablecory: ready for the first serious review.

Resolves #987

@Dotnet-GitSync-Bot
Copy link
Collaborator

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghost
Copy link

ghost commented Jul 13, 2020

Tagging subscribers to this area: @dotnet/ncl
Notify danmosemsft if you want to be subscribed.

@ManickaP ManickaP force-pushed the mapichov/987_http_version_selection branch 4 times, most recently from 557f51b to eda0fde Compare July 18, 2020 10:20
@ManickaP ManickaP force-pushed the mapichov/987_http_version_selection branch from eda0fde to dafe13f Compare July 21, 2020 18:15
Copy link
Member Author

Choose a reason for hiding this comment

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

@scalablecory could you please check whether the expected versions/exceptions correspond to required behavior?
Especially when H3 is involved. I'm really not sure if, for instance, we should downgrade to H2 or go directly for H1 etc.

@ManickaP ManickaP marked this pull request as ready for review July 21, 2020 20:55
@ManickaP ManickaP changed the title [WIP] HTTP Version Selection HTTP Version Selection Jul 21, 2020
@ManickaP
Copy link
Member Author

/azp run runtime-libraries outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@scalablecory scalablecory left a comment

Choose a reason for hiding this comment

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

Initial review -- looks good. Would like to give it a 2nd more in depth pass when I'm more awake.

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

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.

Besides a couple of comment below, LGTM.

Copy link
Contributor

@scalablecory scalablecory left a comment

Choose a reason for hiding this comment

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

some minor comments, otherwise looks good.

}
if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http11)

var buffer = new byte[24];
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we construct this server with a bool unencryptedProtocolDetection = false and throw if !unencryptedProtocolDetection && !_options.UseSsl?

I am worried that we will hide test bugs by accidentally using HTTP/1 when HTTP/2 was wanted, etc. -- this behavior should be off by default.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is enforced in ClearTextVersion in HttpAgnosticOptions which defaults to HttpVersion.Version11.
So unless you construct the server with ClearTextVersion == HttpVersion.Unknown it won't do any unencrypted protocol detection.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed, I removed the default of HTTP/1.1 and I'm explicitly checking for null ClearTextVersion and throwing if not set.

return ValueTask.FromException<(HttpConnectionBase? connection, bool isNewConnection, HttpResponseMessage? failureResponse)>
(new HttpRequestException(SR.Format(SR.net_http_requested_version_not_enabled, request.Version, request.VersionPolicy, 3)));
}
if (request.Version.Major >= 2 && !_http2Enabled)
Copy link
Member

Choose a reason for hiding this comment

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

What happens if requested version is HTTP/3, _http3Enabled is true, but _http2Enabled is false? This is going to throw; that's desirable?

Copy link
Member Author

@ManickaP ManickaP Aug 10, 2020

Choose a reason for hiding this comment

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

I see what you're pointing at, I'll fix it.
However, with how we implemented HttpConnectionSettings._maxHttpVersion, it's not possible to have H3 enabled while H2 disabled.

No, you're right as usual 😄. It might happen, if ALPN 'disables' H2 while we get H3 authority via Alt-Svc... I'd fix it anyway though.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

}

// Do not allow upgrades for synchronous requests, that might lead to asynchronous code-paths.
request.VersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
Copy link
Member

@stephentoub stephentoub Aug 10, 2020

Choose a reason for hiding this comment

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

Doesn't this mean someone could specify RequestVersionOrHigher yet they may silently get a lower version? That seems wrong. Should we instead just throw for unsupported policies?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed, now we throw when user requests upgrades.

@ManickaP
Copy link
Member Author

/azp run runtime-libraries outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ManickaP
Copy link
Member Author

Failures: #33943 and #40606

@ManickaP ManickaP force-pushed the mapichov/987_http_version_selection branch from d92dec0 to 63f7b05 Compare August 11, 2020 07:01
@ManickaP ManickaP merged commit 2adf9da into dotnet:master Aug 12, 2020
@ManickaP ManickaP deleted the mapichov/987_http_version_selection branch August 12, 2020 08:26
@karelz karelz added this to the 5.0.0 milestone Aug 18, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
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.

HTTP version selection

9 participants