Add HTTP/2 pseudo headers as known headers (#19457)

This commit is contained in:
James Newton-King 2020-02-29 16:00:34 +13:00 committed by GitHub
parent 0321390211
commit 41a3c63bc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 1183 additions and 678 deletions

View File

@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// CONNECT - :scheme and :path must be excluded
if (Method == HttpMethod.Connect)
{
if (!String.IsNullOrEmpty(RequestHeaders[HeaderNames.Scheme]) || !String.IsNullOrEmpty(RequestHeaders[HeaderNames.Path]))
if (!String.IsNullOrEmpty(HttpRequestHeaders.HeaderScheme) || !String.IsNullOrEmpty(HttpRequestHeaders.HeaderPath))
{
ResetAndAbort(new ConnectionAbortedException(CoreStrings.Http2ErrorConnectMustNotSendSchemeOrPath), Http2ErrorCode.PROTOCOL_ERROR);
return false;
@ -206,16 +206,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// - That said, we shouldn't allow arbitrary values or use them to populate Request.Scheme, right?
// - For now we'll restrict it to http/s and require it match the transport.
// - We'll need to find some concrete scenarios to warrant unblocking this.
if (!string.Equals(RequestHeaders[HeaderNames.Scheme], Scheme, StringComparison.OrdinalIgnoreCase))
if (!string.Equals(HttpRequestHeaders.HeaderScheme, Scheme, StringComparison.OrdinalIgnoreCase))
{
ResetAndAbort(new ConnectionAbortedException(
CoreStrings.FormatHttp2StreamErrorSchemeMismatch(RequestHeaders[HeaderNames.Scheme], Scheme)), Http2ErrorCode.PROTOCOL_ERROR);
CoreStrings.FormatHttp2StreamErrorSchemeMismatch(HttpRequestHeaders.HeaderScheme, Scheme)), Http2ErrorCode.PROTOCOL_ERROR);
return false;
}
// :path (and query) - Required
// Must start with / except may be * for OPTIONS
var path = RequestHeaders[HeaderNames.Path].ToString();
var path = HttpRequestHeaders.HeaderPath.ToString();
RawTarget = path;
// OPTIONS - https://tools.ietf.org/html/rfc7540#section-8.1.2.3
@ -252,7 +252,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
private bool TryValidateMethod()
{
// :method
_methodText = RequestHeaders[HeaderNames.Method].ToString();
_methodText = HttpRequestHeaders.HeaderMethod.ToString();
Method = HttpUtilities.GetKnownMethod(_methodText);
if (Method == HttpMethod.None)
@ -278,7 +278,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// :authority (optional)
// Prefer this over Host
var authority = RequestHeaders[HeaderNames.Authority];
var authority = HttpRequestHeaders.HeaderAuthority;
var host = HttpRequestHeaders.HeaderHost;
if (!StringValues.IsNullOrEmpty(authority))
{

View File

@ -19,6 +19,10 @@ namespace CodeGenerator
{
var requestPrimaryHeaders = new[]
{
":authority",
":method",
":path",
":scheme",
"Accept",
"Connection",
"Host",
@ -72,6 +76,10 @@ namespace CodeGenerator
};
RequestHeaders = commonHeaders.Concat(new[]
{
":authority",
":method",
":path",
":scheme",
"Accept",
"Accept-Charset",
"Accept-Encoding",
@ -247,7 +255,7 @@ namespace CodeGenerator
{
public string Name { get; set; }
public int Index { get; set; }
public string Identifier => Name.Replace("-", "");
public string Identifier => ResolveIdentifier(Name);
public byte[] Bytes => Encoding.ASCII.GetBytes($"\r\n{Name}: ");
public int BytesOffset { get; set; }
@ -264,6 +272,21 @@ namespace CodeGenerator
public string SetBit() => $"_bits |= {"0x" + (1L << Index).ToString("x")}L";
public string ClearBit() => $"_bits &= ~{"0x" + (1L << Index).ToString("x")}L";
private string ResolveIdentifier(string name)
{
var identifer = name.Replace("-", "");
// Pseudo headers start with a colon. A colon isn't valid in C# names so
// remove it and pascal case the header name. e.g. :path -> Path, :scheme -> Scheme.
// This identifier will match the names in HeadersNames.cs
if (identifer.StartsWith(':'))
{
identifer = char.ToUpper(identifer[1]) + identifer.Substring(2);
}
return identifer;
}
private void GetMaskAndComp(string name, int offset, int count, out ulong mask, out ulong comp)
{
mask = 0;