Add HTTP/2 HPack static compression (#19521)

This commit is contained in:
James Newton-King 2020-03-05 17:08:53 +13:00 committed by GitHub
parent 2fb22f6852
commit 5aa86873c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 828 additions and 407 deletions

View File

@ -14,6 +14,81 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
internal enum KnownHeaderType
{
Unknown,
Accept,
AcceptCharset,
AcceptEncoding,
AcceptLanguage,
AcceptRanges,
AccessControlAllowCredentials,
AccessControlAllowHeaders,
AccessControlAllowMethods,
AccessControlAllowOrigin,
AccessControlExposeHeaders,
AccessControlMaxAge,
AccessControlRequestHeaders,
AccessControlRequestMethod,
Age,
Allow,
AltSvc,
Authority,
Authorization,
CacheControl,
Connection,
ContentEncoding,
ContentLanguage,
ContentLength,
ContentLocation,
ContentMD5,
ContentRange,
ContentType,
Cookie,
CorrelationContext,
Date,
DNT,
ETag,
Expect,
Expires,
From,
Host,
IfMatch,
IfModifiedSince,
IfNoneMatch,
IfRange,
IfUnmodifiedSince,
KeepAlive,
LastModified,
Location,
MaxForwards,
Method,
Origin,
Path,
Pragma,
ProxyAuthenticate,
ProxyAuthorization,
Range,
Referer,
RequestId,
RetryAfter,
Scheme,
Server,
SetCookie,
TE,
TraceParent,
TraceState,
Trailer,
TransferEncoding,
Translate,
Upgrade,
UpgradeInsecureRequests,
UserAgent,
Vary,
Via,
Warning,
WWWAuthenticate,
}
internal partial class HttpRequestHeaders
{
@ -6751,6 +6826,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.CacheControl, _collection._headers._CacheControl);
_currentKnownType = KnownHeaderType.CacheControl;
_next = 1;
return true;
}
@ -6758,6 +6834,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Connection, _collection._headers._Connection);
_currentKnownType = KnownHeaderType.Connection;
_next = 2;
return true;
}
@ -6765,6 +6842,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Date, _collection._headers._Date);
_currentKnownType = KnownHeaderType.Date;
_next = 3;
return true;
}
@ -6772,6 +6850,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.KeepAlive, _collection._headers._KeepAlive);
_currentKnownType = KnownHeaderType.KeepAlive;
_next = 4;
return true;
}
@ -6779,6 +6858,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Pragma, _collection._headers._Pragma);
_currentKnownType = KnownHeaderType.Pragma;
_next = 5;
return true;
}
@ -6786,6 +6866,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Trailer, _collection._headers._Trailer);
_currentKnownType = KnownHeaderType.Trailer;
_next = 6;
return true;
}
@ -6793,6 +6874,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.TransferEncoding, _collection._headers._TransferEncoding);
_currentKnownType = KnownHeaderType.TransferEncoding;
_next = 7;
return true;
}
@ -6800,6 +6882,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Upgrade, _collection._headers._Upgrade);
_currentKnownType = KnownHeaderType.Upgrade;
_next = 8;
return true;
}
@ -6807,6 +6890,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Via, _collection._headers._Via);
_currentKnownType = KnownHeaderType.Via;
_next = 9;
return true;
}
@ -6814,6 +6898,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Warning, _collection._headers._Warning);
_currentKnownType = KnownHeaderType.Warning;
_next = 10;
return true;
}
@ -6821,6 +6906,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Allow, _collection._headers._Allow);
_currentKnownType = KnownHeaderType.Allow;
_next = 11;
return true;
}
@ -6828,6 +6914,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentType, _collection._headers._ContentType);
_currentKnownType = KnownHeaderType.ContentType;
_next = 12;
return true;
}
@ -6835,6 +6922,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentEncoding, _collection._headers._ContentEncoding);
_currentKnownType = KnownHeaderType.ContentEncoding;
_next = 13;
return true;
}
@ -6842,6 +6930,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLanguage, _collection._headers._ContentLanguage);
_currentKnownType = KnownHeaderType.ContentLanguage;
_next = 14;
return true;
}
@ -6849,6 +6938,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLocation, _collection._headers._ContentLocation);
_currentKnownType = KnownHeaderType.ContentLocation;
_next = 15;
return true;
}
@ -6856,6 +6946,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentMD5, _collection._headers._ContentMD5);
_currentKnownType = KnownHeaderType.ContentMD5;
_next = 16;
return true;
}
@ -6863,6 +6954,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentRange, _collection._headers._ContentRange);
_currentKnownType = KnownHeaderType.ContentRange;
_next = 17;
return true;
}
@ -6870,6 +6962,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Expires, _collection._headers._Expires);
_currentKnownType = KnownHeaderType.Expires;
_next = 18;
return true;
}
@ -6877,6 +6970,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.LastModified, _collection._headers._LastModified);
_currentKnownType = KnownHeaderType.LastModified;
_next = 19;
return true;
}
@ -6884,6 +6978,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Authority, _collection._headers._Authority);
_currentKnownType = KnownHeaderType.Authority;
_next = 20;
return true;
}
@ -6891,6 +6986,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Method, _collection._headers._Method);
_currentKnownType = KnownHeaderType.Method;
_next = 21;
return true;
}
@ -6898,6 +6994,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Path, _collection._headers._Path);
_currentKnownType = KnownHeaderType.Path;
_next = 22;
return true;
}
@ -6905,6 +7002,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Scheme, _collection._headers._Scheme);
_currentKnownType = KnownHeaderType.Scheme;
_next = 23;
return true;
}
@ -6912,6 +7010,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Accept, _collection._headers._Accept);
_currentKnownType = KnownHeaderType.Accept;
_next = 24;
return true;
}
@ -6919,6 +7018,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AcceptCharset, _collection._headers._AcceptCharset);
_currentKnownType = KnownHeaderType.AcceptCharset;
_next = 25;
return true;
}
@ -6926,6 +7026,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AcceptEncoding, _collection._headers._AcceptEncoding);
_currentKnownType = KnownHeaderType.AcceptEncoding;
_next = 26;
return true;
}
@ -6933,6 +7034,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AcceptLanguage, _collection._headers._AcceptLanguage);
_currentKnownType = KnownHeaderType.AcceptLanguage;
_next = 27;
return true;
}
@ -6940,6 +7042,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Authorization, _collection._headers._Authorization);
_currentKnownType = KnownHeaderType.Authorization;
_next = 28;
return true;
}
@ -6947,6 +7050,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Cookie, _collection._headers._Cookie);
_currentKnownType = KnownHeaderType.Cookie;
_next = 29;
return true;
}
@ -6954,6 +7058,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Expect, _collection._headers._Expect);
_currentKnownType = KnownHeaderType.Expect;
_next = 30;
return true;
}
@ -6961,6 +7066,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.From, _collection._headers._From);
_currentKnownType = KnownHeaderType.From;
_next = 31;
return true;
}
@ -6968,6 +7074,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Host, _collection._headers._Host);
_currentKnownType = KnownHeaderType.Host;
_next = 32;
return true;
}
@ -6975,6 +7082,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.IfMatch, _collection._headers._IfMatch);
_currentKnownType = KnownHeaderType.IfMatch;
_next = 33;
return true;
}
@ -6982,6 +7090,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.IfModifiedSince, _collection._headers._IfModifiedSince);
_currentKnownType = KnownHeaderType.IfModifiedSince;
_next = 34;
return true;
}
@ -6989,6 +7098,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.IfNoneMatch, _collection._headers._IfNoneMatch);
_currentKnownType = KnownHeaderType.IfNoneMatch;
_next = 35;
return true;
}
@ -6996,6 +7106,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.IfRange, _collection._headers._IfRange);
_currentKnownType = KnownHeaderType.IfRange;
_next = 36;
return true;
}
@ -7003,6 +7114,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.IfUnmodifiedSince, _collection._headers._IfUnmodifiedSince);
_currentKnownType = KnownHeaderType.IfUnmodifiedSince;
_next = 37;
return true;
}
@ -7010,6 +7122,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.MaxForwards, _collection._headers._MaxForwards);
_currentKnownType = KnownHeaderType.MaxForwards;
_next = 38;
return true;
}
@ -7017,6 +7130,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ProxyAuthorization, _collection._headers._ProxyAuthorization);
_currentKnownType = KnownHeaderType.ProxyAuthorization;
_next = 39;
return true;
}
@ -7024,6 +7138,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Referer, _collection._headers._Referer);
_currentKnownType = KnownHeaderType.Referer;
_next = 40;
return true;
}
@ -7031,6 +7146,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Range, _collection._headers._Range);
_currentKnownType = KnownHeaderType.Range;
_next = 41;
return true;
}
@ -7038,6 +7154,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.TE, _collection._headers._TE);
_currentKnownType = KnownHeaderType.TE;
_next = 42;
return true;
}
@ -7045,6 +7162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Translate, _collection._headers._Translate);
_currentKnownType = KnownHeaderType.Translate;
_next = 43;
return true;
}
@ -7052,6 +7170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.UserAgent, _collection._headers._UserAgent);
_currentKnownType = KnownHeaderType.UserAgent;
_next = 44;
return true;
}
@ -7059,6 +7178,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.DNT, _collection._headers._DNT);
_currentKnownType = KnownHeaderType.DNT;
_next = 45;
return true;
}
@ -7066,6 +7186,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.UpgradeInsecureRequests, _collection._headers._UpgradeInsecureRequests);
_currentKnownType = KnownHeaderType.UpgradeInsecureRequests;
_next = 46;
return true;
}
@ -7073,6 +7194,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.RequestId, _collection._headers._RequestId);
_currentKnownType = KnownHeaderType.RequestId;
_next = 47;
return true;
}
@ -7080,6 +7202,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.CorrelationContext, _collection._headers._CorrelationContext);
_currentKnownType = KnownHeaderType.CorrelationContext;
_next = 48;
return true;
}
@ -7087,6 +7210,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.TraceParent, _collection._headers._TraceParent);
_currentKnownType = KnownHeaderType.TraceParent;
_next = 49;
return true;
}
@ -7094,6 +7218,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.TraceState, _collection._headers._TraceState);
_currentKnownType = KnownHeaderType.TraceState;
_next = 50;
return true;
}
@ -7101,6 +7226,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Origin, _collection._headers._Origin);
_currentKnownType = KnownHeaderType.Origin;
_next = 51;
return true;
}
@ -7108,6 +7234,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlRequestMethod, _collection._headers._AccessControlRequestMethod);
_currentKnownType = KnownHeaderType.AccessControlRequestMethod;
_next = 52;
return true;
}
@ -7115,6 +7242,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000000000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlRequestHeaders, _collection._headers._AccessControlRequestHeaders);
_currentKnownType = KnownHeaderType.AccessControlRequestHeaders;
_next = 53;
return true;
}
@ -7122,6 +7250,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (_collection._contentLength.HasValue)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLength, HeaderUtilities.FormatNonNegativeInt64(_collection._contentLength.Value));
_currentKnownType = KnownHeaderType.ContentLength;
_next = 54;
return true;
}
@ -7129,9 +7258,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (!_hasUnknown || !_unknownEnumerator.MoveNext())
{
_current = default(KeyValuePair<string, StringValues>);
_currentKnownType = default;
return false;
}
_current = _unknownEnumerator.Current;
_currentKnownType = KnownHeaderType.Unknown;
return true;
}
}
@ -12161,6 +12292,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.CacheControl, _collection._headers._CacheControl);
_currentKnownType = KnownHeaderType.CacheControl;
_next = 1;
return true;
}
@ -12168,6 +12300,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Connection, _collection._headers._Connection);
_currentKnownType = KnownHeaderType.Connection;
_next = 2;
return true;
}
@ -12175,6 +12308,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Date, _collection._headers._Date);
_currentKnownType = KnownHeaderType.Date;
_next = 3;
return true;
}
@ -12182,6 +12316,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.KeepAlive, _collection._headers._KeepAlive);
_currentKnownType = KnownHeaderType.KeepAlive;
_next = 4;
return true;
}
@ -12189,6 +12324,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Pragma, _collection._headers._Pragma);
_currentKnownType = KnownHeaderType.Pragma;
_next = 5;
return true;
}
@ -12196,6 +12332,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Trailer, _collection._headers._Trailer);
_currentKnownType = KnownHeaderType.Trailer;
_next = 6;
return true;
}
@ -12203,6 +12340,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.TransferEncoding, _collection._headers._TransferEncoding);
_currentKnownType = KnownHeaderType.TransferEncoding;
_next = 7;
return true;
}
@ -12210,6 +12348,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Upgrade, _collection._headers._Upgrade);
_currentKnownType = KnownHeaderType.Upgrade;
_next = 8;
return true;
}
@ -12217,6 +12356,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Via, _collection._headers._Via);
_currentKnownType = KnownHeaderType.Via;
_next = 9;
return true;
}
@ -12224,6 +12364,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Warning, _collection._headers._Warning);
_currentKnownType = KnownHeaderType.Warning;
_next = 10;
return true;
}
@ -12231,6 +12372,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Allow, _collection._headers._Allow);
_currentKnownType = KnownHeaderType.Allow;
_next = 11;
return true;
}
@ -12238,6 +12380,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentType, _collection._headers._ContentType);
_currentKnownType = KnownHeaderType.ContentType;
_next = 12;
return true;
}
@ -12245,6 +12388,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentEncoding, _collection._headers._ContentEncoding);
_currentKnownType = KnownHeaderType.ContentEncoding;
_next = 13;
return true;
}
@ -12252,6 +12396,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLanguage, _collection._headers._ContentLanguage);
_currentKnownType = KnownHeaderType.ContentLanguage;
_next = 14;
return true;
}
@ -12259,6 +12404,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLocation, _collection._headers._ContentLocation);
_currentKnownType = KnownHeaderType.ContentLocation;
_next = 15;
return true;
}
@ -12266,6 +12412,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentMD5, _collection._headers._ContentMD5);
_currentKnownType = KnownHeaderType.ContentMD5;
_next = 16;
return true;
}
@ -12273,6 +12420,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentRange, _collection._headers._ContentRange);
_currentKnownType = KnownHeaderType.ContentRange;
_next = 17;
return true;
}
@ -12280,6 +12428,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Expires, _collection._headers._Expires);
_currentKnownType = KnownHeaderType.Expires;
_next = 18;
return true;
}
@ -12287,6 +12436,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.LastModified, _collection._headers._LastModified);
_currentKnownType = KnownHeaderType.LastModified;
_next = 19;
return true;
}
@ -12294,6 +12444,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AcceptRanges, _collection._headers._AcceptRanges);
_currentKnownType = KnownHeaderType.AcceptRanges;
_next = 20;
return true;
}
@ -12301,6 +12452,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Age, _collection._headers._Age);
_currentKnownType = KnownHeaderType.Age;
_next = 21;
return true;
}
@ -12308,6 +12460,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AltSvc, _collection._headers._AltSvc);
_currentKnownType = KnownHeaderType.AltSvc;
_next = 22;
return true;
}
@ -12315,6 +12468,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ETag, _collection._headers._ETag);
_currentKnownType = KnownHeaderType.ETag;
_next = 23;
return true;
}
@ -12322,6 +12476,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Location, _collection._headers._Location);
_currentKnownType = KnownHeaderType.Location;
_next = 24;
return true;
}
@ -12329,6 +12484,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ProxyAuthenticate, _collection._headers._ProxyAuthenticate);
_currentKnownType = KnownHeaderType.ProxyAuthenticate;
_next = 25;
return true;
}
@ -12336,6 +12492,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x2000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.RetryAfter, _collection._headers._RetryAfter);
_currentKnownType = KnownHeaderType.RetryAfter;
_next = 26;
return true;
}
@ -12343,6 +12500,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x4000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Server, _collection._headers._Server);
_currentKnownType = KnownHeaderType.Server;
_next = 27;
return true;
}
@ -12350,6 +12508,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x8000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.SetCookie, _collection._headers._SetCookie);
_currentKnownType = KnownHeaderType.SetCookie;
_next = 28;
return true;
}
@ -12357,6 +12516,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x10000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.Vary, _collection._headers._Vary);
_currentKnownType = KnownHeaderType.Vary;
_next = 29;
return true;
}
@ -12364,6 +12524,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x20000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.WWWAuthenticate, _collection._headers._WWWAuthenticate);
_currentKnownType = KnownHeaderType.WWWAuthenticate;
_next = 30;
return true;
}
@ -12371,6 +12532,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x40000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlAllowCredentials, _collection._headers._AccessControlAllowCredentials);
_currentKnownType = KnownHeaderType.AccessControlAllowCredentials;
_next = 31;
return true;
}
@ -12378,6 +12540,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x80000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlAllowHeaders, _collection._headers._AccessControlAllowHeaders);
_currentKnownType = KnownHeaderType.AccessControlAllowHeaders;
_next = 32;
return true;
}
@ -12385,6 +12548,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x100000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlAllowMethods, _collection._headers._AccessControlAllowMethods);
_currentKnownType = KnownHeaderType.AccessControlAllowMethods;
_next = 33;
return true;
}
@ -12392,6 +12556,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x200000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlAllowOrigin, _collection._headers._AccessControlAllowOrigin);
_currentKnownType = KnownHeaderType.AccessControlAllowOrigin;
_next = 34;
return true;
}
@ -12399,6 +12564,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x400000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlExposeHeaders, _collection._headers._AccessControlExposeHeaders);
_currentKnownType = KnownHeaderType.AccessControlExposeHeaders;
_next = 35;
return true;
}
@ -12406,6 +12572,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x800000000L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.AccessControlMaxAge, _collection._headers._AccessControlMaxAge);
_currentKnownType = KnownHeaderType.AccessControlMaxAge;
_next = 36;
return true;
}
@ -12413,6 +12580,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (_collection._contentLength.HasValue)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLength, HeaderUtilities.FormatNonNegativeInt64(_collection._contentLength.Value));
_currentKnownType = KnownHeaderType.ContentLength;
_next = 37;
return true;
}
@ -12420,9 +12588,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (!_hasUnknown || !_unknownEnumerator.MoveNext())
{
_current = default(KeyValuePair<string, StringValues>);
_currentKnownType = default;
return false;
}
_current = _unknownEnumerator.Current;
_currentKnownType = KnownHeaderType.Unknown;
return true;
}
}
@ -12668,6 +12838,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if ((_bits & 0x1L) != 0)
{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ETag, _collection._headers._ETag);
_currentKnownType = KnownHeaderType.ETag;
_next = 1;
return true;
}
@ -12676,9 +12847,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
if (!_hasUnknown || !_unknownEnumerator.MoveNext())
{
_current = default(KeyValuePair<string, StringValues>);
_currentKnownType = default;
return false;
}
_current = _unknownEnumerator.Current;
_currentKnownType = KnownHeaderType.Unknown;
return true;
}
}

View File

@ -127,6 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private readonly long _bits;
private int _next;
private KeyValuePair<string, StringValues> _current;
private KnownHeaderType _currentKnownType;
private readonly bool _hasUnknown;
private Dictionary<string, StringValues>.Enumerator _unknownEnumerator;
@ -136,6 +137,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_bits = collection._bits;
_next = 0;
_current = default;
_currentKnownType = default;
_hasUnknown = collection.MaybeUnknown != null;
_unknownEnumerator = _hasUnknown
? collection.MaybeUnknown.GetEnumerator()
@ -144,6 +146,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public KeyValuePair<string, StringValues> Current => _current;
internal KnownHeaderType CurrentKnownType => _currentKnownType;
object IEnumerator.Current => _current;
public void Dispose()

View File

@ -94,6 +94,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private readonly long _bits;
private int _next;
private KeyValuePair<string, StringValues> _current;
private KnownHeaderType _currentKnownType;
private readonly bool _hasUnknown;
private Dictionary<string, StringValues>.Enumerator _unknownEnumerator;
@ -103,6 +104,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_bits = collection._bits;
_next = 0;
_current = default;
_currentKnownType = default;
_hasUnknown = collection.MaybeUnknown != null;
_unknownEnumerator = _hasUnknown
? collection.MaybeUnknown.GetEnumerator()
@ -111,6 +113,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public KeyValuePair<string, StringValues> Current => _current;
internal KnownHeaderType CurrentKnownType => _currentKnownType;
object IEnumerator.Current => _current;
public void Dispose()

View File

@ -43,6 +43,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private readonly long _bits;
private int _next;
private KeyValuePair<string, StringValues> _current;
private KnownHeaderType _currentKnownType;
private readonly bool _hasUnknown;
private Dictionary<string, StringValues>.Enumerator _unknownEnumerator;
@ -52,6 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_bits = collection._bits;
_next = 0;
_current = default;
_currentKnownType = default;
_hasUnknown = collection.MaybeUnknown != null;
_unknownEnumerator = _hasUnknown
? collection.MaybeUnknown.GetEnumerator()
@ -60,6 +62,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
public KeyValuePair<string, StringValues> Current => _current;
internal KnownHeaderType CurrentKnownType => _currentKnownType;
object IEnumerator.Current => _current;
public void Dispose()

View File

@ -0,0 +1,157 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Net.Http;
using System.Net.Http.HPack;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
{
internal static class HPackHeaderWriter
{
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(int statusCode, Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
if (!HPackEncoder.EncodeStatusHeader(statusCode, buffer, out var statusCodeLength))
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
if (!headersEnumerator.MoveNext())
{
length = statusCodeLength;
return true;
}
// We're ok with not throwing if no headers were encoded because we've already encoded the status.
// There is a small chance that the header will encode if there is no other content in the next HEADERS frame.
var done = EncodeHeaders(headersEnumerator, buffer.Slice(statusCodeLength), throwIfNoneEncoded: false, out var headersLength);
length = statusCodeLength + headersLength;
return done;
}
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
if (!headersEnumerator.MoveNext())
{
length = 0;
return true;
}
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
}
/// <summary>
/// Continue encoding headers in the next HEADERS frame. The enumerator should already have a current value.
/// </summary>
public static bool ContinueEncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, out int length)
{
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
}
private static bool EncodeHeaders(Http2HeadersEnumerator headersEnumerator, Span<byte> buffer, bool throwIfNoneEncoded, out int length)
{
var currentLength = 0;
do
{
if (!EncodeHeader(headersEnumerator.KnownHeaderType, headersEnumerator.Current.Key, headersEnumerator.Current.Value, buffer.Slice(currentLength), out int headerLength))
{
// The the header wasn't written and no headers have been written then the header is too large.
// Throw an error to avoid an infinite loop of attempting to write large header.
if (currentLength == 0 && throwIfNoneEncoded)
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length = currentLength;
return false;
}
currentLength += headerLength;
}
while (headersEnumerator.MoveNext());
length = currentLength;
return true;
}
private static bool EncodeHeader(KnownHeaderType knownHeaderType, string name, string value, Span<byte> buffer, out int length)
{
var hPackStaticTableId = GetResponseHeaderStaticTableId(knownHeaderType);
if (hPackStaticTableId == -1)
{
return HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, buffer, out length);
}
else
{
return HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexing(hPackStaticTableId, value, buffer, out length);
}
}
private static int GetResponseHeaderStaticTableId(KnownHeaderType responseHeaderType)
{
switch (responseHeaderType)
{
case KnownHeaderType.CacheControl:
return H2StaticTable.CacheControl;
case KnownHeaderType.Date:
return H2StaticTable.Date;
case KnownHeaderType.TransferEncoding:
return H2StaticTable.TransferEncoding;
case KnownHeaderType.Via:
return H2StaticTable.Via;
case KnownHeaderType.Allow:
return H2StaticTable.Allow;
case KnownHeaderType.ContentType:
return H2StaticTable.ContentType;
case KnownHeaderType.ContentEncoding:
return H2StaticTable.ContentEncoding;
case KnownHeaderType.ContentLanguage:
return H2StaticTable.ContentLanguage;
case KnownHeaderType.ContentLocation:
return H2StaticTable.ContentLocation;
case KnownHeaderType.ContentRange:
return H2StaticTable.ContentRange;
case KnownHeaderType.Expires:
return H2StaticTable.Expires;
case KnownHeaderType.LastModified:
return H2StaticTable.LastModified;
case KnownHeaderType.AcceptRanges:
return H2StaticTable.AcceptRanges;
case KnownHeaderType.Age:
return H2StaticTable.Age;
case KnownHeaderType.ETag:
return H2StaticTable.ETag;
case KnownHeaderType.Location:
return H2StaticTable.Location;
case KnownHeaderType.ProxyAuthenticate:
return H2StaticTable.ProxyAuthenticate;
case KnownHeaderType.RetryAfter:
return H2StaticTable.RetryAfter;
case KnownHeaderType.Server:
return H2StaticTable.Server;
case KnownHeaderType.SetCookie:
return H2StaticTable.SetCookie;
case KnownHeaderType.Vary:
return H2StaticTable.Vary;
case KnownHeaderType.WWWAuthenticate:
return H2StaticTable.WwwAuthenticate;
case KnownHeaderType.AccessControlAllowOrigin:
return H2StaticTable.AccessControlAllowOrigin;
case KnownHeaderType.ContentLength:
return H2StaticTable.ContentLength;
default:
return -1;
}
}
}
}

View File

@ -7,6 +7,7 @@ using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipelines;
using System.Net.Http;
using System.Net.Http.HPack;
using System.Threading;
using System.Threading.Tasks;
@ -27,7 +28,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
private readonly object _writeLock = new object();
private readonly Http2Frame _outgoingFrame;
private readonly HPackEncoder _hpackEncoder = new HPackEncoder();
private readonly Http2HeadersEnumerator _headersEnumerator = new Http2HeadersEnumerator();
private readonly ConcurrentPipeWriter _outputWriter;
private readonly ConnectionContext _connectionContext;
@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Initialize(headers);
_outgoingFrame.PrepareHeaders(headerFrameFlags, streamId);
var buffer = _headerEncodingBuffer.AsSpan();
var done = _hpackEncoder.BeginEncode(statusCode, _headersEnumerator, buffer, out var payloadLength);
var done = HPackHeaderWriter.BeginEncodeHeaders(statusCode, _headersEnumerator, buffer, out var payloadLength);
FinishWritingHeaders(streamId, payloadLength, done);
}
catch (HPackEncodingException hex)
@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Initialize(headers);
_outgoingFrame.PrepareHeaders(Http2HeadersFrameFlags.END_STREAM, streamId);
var buffer = _headerEncodingBuffer.AsSpan();
var done = _hpackEncoder.BeginEncode(_headersEnumerator, buffer, out var payloadLength);
var done = HPackHeaderWriter.BeginEncodeHeaders(_headersEnumerator, buffer, out var payloadLength);
FinishWritingHeaders(streamId, payloadLength, done);
}
catch (HPackEncodingException hex)
@ -230,7 +230,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
{
_outgoingFrame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
done = _hpackEncoder.Encode(buffer, out payloadLength);
done = HPackHeaderWriter.ContinueEncodeHeaders(_headersEnumerator, buffer, out payloadLength);
_outgoingFrame.PayloadLength = payloadLength;
if (done)

View File

@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
private IEnumerator<KeyValuePair<string, StringValues>> _genericEnumerator;
private StringValues.Enumerator _stringValuesEnumerator;
public KnownHeaderType KnownHeaderType { get; private set; }
public KeyValuePair<string, string> Current { get; private set; }
object IEnumerator.Current => Current;
@ -32,6 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
}
public void Initialize(HttpResponseTrailers headers)
@ -43,6 +45,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
}
public void Initialize(IDictionary<string, StringValues> headers)
@ -54,6 +57,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_stringValuesEnumerator = default;
Current = default;
KnownHeaderType = default;
}
public bool MoveNext()
@ -106,6 +110,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _genericEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = default;
return true;
}
}
@ -119,6 +124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _trailersEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = _trailersEnumerator.CurrentKnownType;
return true;
}
}
@ -132,6 +138,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
else
{
enumerator = _headersEnumerator.Current.Value.GetEnumerator();
KnownHeaderType = _headersEnumerator.CurrentKnownType;
return true;
}
}
@ -152,6 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_headersEnumerator.Reset();
}
_stringValuesEnumerator = default;
KnownHeaderType = default;
}
public void Dispose()

View File

@ -3,17 +3,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.HPack;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.Extensions.Primitives;
using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
public class HPackEncoderTests
public class HPackHeaderWriterTests
{
public static TheoryData<KeyValuePair<string, string>[], byte[], int?> SinglePayloadData
{
@ -94,16 +91,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[MemberData(nameof(SinglePayloadData))]
public void EncodesHeadersInSinglePayloadWhenSpaceAvailable(KeyValuePair<string, string>[] headers, byte[] expectedPayload, int? statusCode)
{
var encoder = new HPackEncoder();
var payload = new byte[1024];
var length = 0;
if (statusCode.HasValue)
{
Assert.True(encoder.BeginEncode(statusCode.Value, GetHeadersEnumerator(headers), payload, out length));
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(statusCode.Value, GetHeadersEnumerator(headers), payload, out length));
}
else
{
Assert.True(encoder.BeginEncode(GetHeadersEnumerator(headers), payload, out length));
Assert.True(HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out length));
}
Assert.Equal(expectedPayload.Length, length);
@ -120,10 +116,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[InlineData(false)]
public void EncodesHeadersInMultiplePayloadsWhenSpaceNotAvailable(bool exactSize)
{
var encoder = new HPackEncoder();
var statusCode = 200;
var headers = new []
var headers = new[]
{
new KeyValuePair<string, string>("date", "Mon, 24 Jul 2017 19:22:30 GMT"),
new KeyValuePair<string, string>("content-type", "text/html; charset=utf-8"),
@ -161,31 +155,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Span<byte> payload = new byte[1024];
var offset = 0;
var headerEnumerator = GetHeadersEnumerator(headers);
// When !exactSize, slices are one byte short of fitting the next header
var sliceLength = expectedStatusCodePayload.Length + (exactSize ? 0 : expectedDateHeaderPayload.Length - 1);
Assert.False(encoder.BeginEncode(statusCode, GetHeadersEnumerator(headers), payload.Slice(offset, sliceLength), out var length));
Assert.False(HPackHeaderWriter.BeginEncodeHeaders(statusCode, headerEnumerator, payload.Slice(offset, sliceLength), out var length));
Assert.Equal(expectedStatusCodePayload.Length, length);
Assert.Equal(expectedStatusCodePayload, payload.Slice(0, length).ToArray());
offset += length;
sliceLength = expectedDateHeaderPayload.Length + (exactSize ? 0 : expectedContentTypeHeaderPayload.Length - 1);
Assert.False(encoder.Encode(payload.Slice(offset, sliceLength), out length));
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedDateHeaderPayload.Length, length);
Assert.Equal(expectedDateHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
sliceLength = expectedContentTypeHeaderPayload.Length + (exactSize ? 0 : expectedServerHeaderPayload.Length - 1);
Assert.False(encoder.Encode(payload.Slice(offset, sliceLength), out length));
Assert.False(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedContentTypeHeaderPayload.Length, length);
Assert.Equal(expectedContentTypeHeaderPayload, payload.Slice(offset, length).ToArray());
offset += length;
sliceLength = expectedServerHeaderPayload.Length;
Assert.True(encoder.Encode(payload.Slice(offset, sliceLength), out length));
Assert.True(HPackHeaderWriter.ContinueEncodeHeaders(headerEnumerator, payload.Slice(offset, sliceLength), out length));
Assert.Equal(expectedServerHeaderPayload.Length, length);
Assert.Equal(expectedServerHeaderPayload, payload.Slice(offset, length).ToArray());
}

View File

@ -30,7 +30,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
private Http2Connection _connection;
private Http2HeadersEnumerator _requestHeadersEnumerator;
private int _currentStreamId;
private HPackEncoder _hpackEncoder;
private byte[] _headersBuffer;
[GlobalSetup]
@ -47,7 +46,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
_httpRequestHeaders.Append(HeaderNames.Scheme, new StringValues("http"));
_httpRequestHeaders.Append(HeaderNames.Authority, new StringValues("localhost:80"));
_hpackEncoder = new HPackEncoder();
_headersBuffer = new byte[1024 * 16];
var serviceContext = new ServiceContext
@ -78,7 +76,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
_ = _connection.ProcessRequestsAsync(new DummyApplication());
_pipe.Writer.Write(Http2Connection.ClientPreface);
PipeWriterHttp2FrameExtensions.WriteSettings(_pipe.Writer, new Http2PeerSettings());
_pipe.Writer.WriteSettings(new Http2PeerSettings());
_pipe.Writer.FlushAsync().GetAwaiter().GetResult();
}
@ -86,7 +84,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
public async Task EmptyRequest()
{
_requestHeadersEnumerator.Initialize(_httpRequestHeaders);
PipeWriterHttp2FrameExtensions.WriteStartStream(_pipe.Writer, streamId: _currentStreamId, _requestHeadersEnumerator, _hpackEncoder, _headersBuffer, endStream: true);
_requestHeadersEnumerator.MoveNext();
_pipe.Writer.WriteStartStream(streamId: _currentStreamId, _requestHeadersEnumerator, _headersBuffer, endStream: true);
_currentStreamId += 2;
await _pipe.Writer.FlushAsync();
}

View File

@ -562,6 +562,9 @@ namespace CodeGenerator
var responseTrailers = ResponseTrailers;
var allHeaderNames = RequestHeaders.Concat(ResponseHeaders).Concat(ResponseTrailers)
.Select(h => h.Identifier).Distinct().OrderBy(n => n).ToArray();
var loops = new[]
{
new
@ -612,6 +615,11 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{{
internal enum KnownHeaderType
{{
Unknown,{Each(allHeaderNames, n => @"
" + n + ",")}
}}
{Each(loops, loop => $@"
internal partial class {loop.ClassName}
{{{(loop.Bytes != null ?
@ -1058,6 +1066,7 @@ $@" private void Clear(long bitsToClear)
if ({header.TestBit()})
{{
_current = new KeyValuePair<string, StringValues>(HeaderNames.{header.Identifier}, _collection._headers._{header.Identifier});
_currentKnownType = KnownHeaderType.{header.Identifier};
_next = {header.Index + 1};
return true;
}}")}
@ -1065,6 +1074,7 @@ $@" private void Clear(long bitsToClear)
if (_collection._contentLength.HasValue)
{{
_current = new KeyValuePair<string, StringValues>(HeaderNames.ContentLength, HeaderUtilities.FormatNonNegativeInt64(_collection._contentLength.Value));
_currentKnownType = KnownHeaderType.ContentLength;
_next = {loop.Headers.Count()};
return true;
}}" : "")}
@ -1072,9 +1082,11 @@ $@" private void Clear(long bitsToClear)
if (!_hasUnknown || !_unknownEnumerator.MoveNext())
{{
_current = default(KeyValuePair<string, StringValues>);
_currentKnownType = default;
return false;
}}
_current = _unknownEnumerator.Current;
_currentKnownType = KnownHeaderType.Unknown;
return true;
}}
}}

View File

@ -24,13 +24,13 @@ namespace Microsoft.AspNetCore.Testing
writer.Write(payload);
}
public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, HPackEncoder hpackEncoder, byte[] headerEncodingBuffer, bool endStream)
public static void WriteStartStream(this PipeWriter writer, int streamId, Http2HeadersEnumerator headers, byte[] headerEncodingBuffer, bool endStream)
{
var frame = new Http2Frame();
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
var buffer = headerEncodingBuffer.AsSpan();
var done = hpackEncoder.BeginEncode(headers, buffer, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(headers, buffer, out var length);
frame.PayloadLength = length;
if (done)
@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Testing
{
frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
done = hpackEncoder.Encode(buffer, out length);
done = HPackHeaderWriter.ContinueEncodeHeaders(headers, buffer, out length);
frame.PayloadLength = length;
if (done)
@ -63,6 +63,22 @@ namespace Microsoft.AspNetCore.Testing
}
}
public static void WriteStartStream(this PipeWriter writer, int streamId, Span<byte> headerData, bool endStream)
{
var frame = new Http2Frame();
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
frame.PayloadLength = headerData.Length;
frame.HeadersFlags = Http2HeadersFrameFlags.END_HEADERS;
if (endStream)
{
frame.HeadersFlags |= Http2HeadersFrameFlags.END_STREAM;
}
Http2FrameWriter.WriteHeader(frame, writer);
writer.Write(headerData);
}
public static void WriteData(this PipeWriter writer, int streamId, Memory<byte> data, bool endStream)
{
var frame = new Http2Frame();

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, requestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, requestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -171,7 +171,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
appDelegateTcs.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -194,7 +194,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
appDelegateTcs.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -304,7 +304,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[length], endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
// The client's settings is still defaulted to Http2PeerSettings.MinAllowedMaxFrameSize so the echo response will come back in two separate frames
@ -333,7 +333,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -359,7 +359,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -402,7 +402,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _noData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -551,7 +551,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var stream1DataFrame1 = await ExpectAsync(Http2FrameType.DATA,
@ -562,7 +562,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
var stream3DataFrame1 = await ExpectAsync(Http2FrameType.DATA,
@ -631,7 +631,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -683,7 +683,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 0);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
@ -761,7 +761,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
stream3ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -776,7 +776,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
stream1ReadFinished.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -803,7 +803,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataWithPaddingAsync(1, _helloWorldBytes, padLength, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -848,7 +848,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -907,7 +907,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -976,7 +976,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1151,7 +1151,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _postRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1193,7 +1193,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1243,7 +1243,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1347,7 +1347,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1368,7 +1368,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1402,7 +1402,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1417,7 +1417,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1437,7 +1437,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPaddingAsync(1, _browserRequestHeaders, padLength, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1454,7 +1454,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPriorityAsync(1, _browserRequestHeaders, priority: 42, streamDependency: 0, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1474,7 +1474,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersWithPaddingAndPriorityAsync(1, _browserRequestHeaders, padLength, priority: 42, streamDependency: 0, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1500,7 +1500,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The second stream should end first, since the first one is waiting for the request body.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1512,7 +1512,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, _requestTrailers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1546,7 +1546,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1596,14 +1596,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
finishSecondRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
finishFirstRequest.TrySetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1629,7 +1629,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
requestBlocker.SetResult(0);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1672,7 +1672,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1715,7 +1715,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -1939,7 +1939,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2084,7 +2084,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2222,7 +2222,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2247,7 +2247,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The headers, but not the data for stream 3, can be sent prior to any window updates.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
@ -2331,7 +2331,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(streamId, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: streamId);
@ -2811,7 +2811,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_connection.ServerSettings.MaxFrameSize = Http2PeerSettings.MaxAllowedMaxFrameSize;
// This includes the default response headers such as :status, etc
var defaultResponseHeaderLength = 37;
var defaultResponseHeaderLength = 33;
var headerValueLength = Http2PeerSettings.MinAllowedMaxFrameSize;
// First byte is always 0
// Second byte is the length of header name which is 1
@ -2881,7 +2881,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3030,7 +3030,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3043,7 +3043,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await SendDataAsync(3, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -3116,7 +3116,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3139,13 +3139,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The headers, but not the data for the stream, can still be sent.
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await StartStreamAsync(5, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 5);
@ -3209,7 +3209,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(streamId, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: streamId);
@ -3442,7 +3442,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3499,7 +3499,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3538,7 +3538,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -3590,7 +3590,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _twoContinuationsRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3616,7 +3616,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// The second stream should end first, since the first one is waiting for the request body.
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 3);
@ -3639,7 +3639,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendContinuationAsync(1, Http2ContinuationFrameFlags.END_HEADERS, trailers);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3661,8 +3661,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
{
await InitializeConnectionAsync(_readHeadersApplication);
await SendHeadersAsync(1, Http2HeadersFrameFlags.NONE, _oneContinuationRequestHeaders);
await SendContinuationAsync(3, Http2ContinuationFrameFlags.END_HEADERS);
var headersEnumerator = GetHeadersEnumerator(_oneContinuationRequestHeaders);
await SendHeadersAsync(1, Http2HeadersFrameFlags.NONE, headersEnumerator);
await SendContinuationAsync(3, Http2ContinuationFrameFlags.END_HEADERS, headersEnumerator);
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
ignoreNonGoAwayFrames: false,
@ -3736,7 +3737,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendEmptyContinuationFrameAsync(1, Http2ContinuationFrameFlags.END_HEADERS);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3751,7 +3752,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 12361,
withLength: 12343,
withFlags: (byte)Http2HeadersFrameFlags.END_STREAM,
withStreamId: 1);
var continuationFrame1 = await ExpectAsync(Http2FrameType.CONTINUATION,
@ -3910,7 +3911,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3960,7 +3961,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3994,7 +3995,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -4007,7 +4008,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await SendDataAsync(3, _helloBytes, true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -4097,7 +4098,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);

View File

@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 70,
withLength: 52,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 71,
withLength: 53,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 75,
withLength: 57,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 76,
withLength: 58,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -193,7 +193,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 118,
withLength: 100,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -326,7 +326,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -355,7 +355,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 65,
withLength: 47,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -386,7 +386,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 65,
withLength: 47,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -417,7 +417,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 65,
withLength: 47,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 65,
withLength: 47,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -570,7 +570,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -611,7 +611,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -655,7 +655,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -698,7 +698,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -751,7 +751,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[8], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -983,7 +983,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1015,7 +1015,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.RST_STREAM,
@ -1054,7 +1054,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1092,7 +1092,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1125,7 +1125,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1160,7 +1160,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1198,7 +1198,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1236,7 +1236,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1276,7 +1276,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1323,7 +1323,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1361,7 +1361,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1397,7 +1397,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1441,7 +1441,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1475,7 +1475,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1508,7 +1508,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -1552,7 +1552,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1591,7 +1591,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 59,
withLength: 41,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1634,7 +1634,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1674,7 +1674,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[6], endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 59,
withLength: 41,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1733,7 +1733,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[6], endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 59,
withLength: 41,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1788,7 +1788,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, new byte[12], endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -1814,7 +1814,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1852,7 +1852,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_STREAM | Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
@ -1883,7 +1883,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame1 = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var trailersFrame1 = await ExpectAsync(Http2FrameType.HEADERS,
@ -1894,7 +1894,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(3, _browserRequestHeaders, endStream: true);
var headersFrame2 = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 3);
@ -1930,7 +1930,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -1980,7 +1980,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2039,7 +2039,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2074,7 +2074,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2124,7 +2124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true).DefaultTimeout();
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1).DefaultTimeout();
@ -2189,7 +2189,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2235,7 +2235,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2269,7 +2269,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -2532,7 +2532,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -2623,7 +2623,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, _browserRequestHeaders, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2671,7 +2671,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// Just the StatusCode gets written before aborting in the continuation frame
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.NONE,
withStreamId: 1);
@ -2700,7 +2700,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -2743,7 +2743,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -2789,7 +2789,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2835,7 +2835,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2884,7 +2884,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2937,7 +2937,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -2987,7 +2987,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3037,7 +3037,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3080,7 +3080,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3126,7 +3126,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
var dataFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3168,7 +3168,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3213,7 +3213,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3279,7 +3279,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3325,7 +3325,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3361,7 +3361,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3413,7 +3413,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -3465,7 +3465,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3498,7 +3498,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
// Don't receive content length because we called WriteAsync which caused an invalid response
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS | (byte)Http2HeadersFrameFlags.END_STREAM,
withStreamId: 1);
@ -3531,7 +3531,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3583,7 +3583,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3639,7 +3639,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var trailersFrame = await ExpectAsync(Http2FrameType.HEADERS,
@ -3705,7 +3705,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3761,7 +3761,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3826,7 +3826,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -3885,7 +3885,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -3941,7 +3941,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4003,7 +4003,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4077,7 +4077,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4153,7 +4153,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4224,7 +4224,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 56,
withLength: 38,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4296,7 +4296,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4380,7 +4380,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4461,7 +4461,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4548,7 +4548,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await StartStreamAsync(1, headers, endStream: false);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS),
withStreamId: 1);
var bodyFrame = await ExpectAsync(Http2FrameType.DATA,
@ -4583,30 +4583,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal("Custom Value", _decodedHeaders["CustomName"]);
}
// :method = GET
// :path = /
// :scheme = http
// X-Test = £
private static readonly byte[] LatinHeaderData = new byte[]
{
0, 7, 58, 109, 101, 116, 104, 111, 100, 3, 71, 69, 84, 0, 5, 58, 112, 97, 116,
104, 1, 47, 0, 7, 58, 115, 99, 104, 101, 109, 101, 4, 104, 116, 116, 112, 0,
6, 120, 45, 116, 101, 115, 116, 1, 163
};
[Fact]
public async Task HEADERS_Received_Latin1_AcceptedWhenLatin1OptionIsConfigured()
{
_serviceContext.ServerOptions.Latin1RequestHeaders = true;
var headers = new[]
{
new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
new KeyValuePair<string, string>(HeaderNames.Path, "/"),
new KeyValuePair<string, string>(HeaderNames.Scheme, "http"),
// The HPackEncoder will encode £ as 0xA3 aka Latin1 encoding.
new KeyValuePair<string, string>("X-Test", "£"),
};
await InitializeConnectionAsync(context =>
{
Assert.Equal("£", context.Request.Headers["X-Test"]);
return Task.CompletedTask;
});
await StartStreamAsync(1, headers, endStream: true);
await StartStreamAsync(1, LatinHeaderData, endStream: true);
var headersFrame = await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -4623,18 +4625,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
[Fact]
public async Task HEADERS_Received_Latin1_RejectedWhenLatin1OptionIsNotConfigured()
{
var headers = new[]
{
new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
new KeyValuePair<string, string>(HeaderNames.Path, "/"),
new KeyValuePair<string, string>(HeaderNames.Scheme, "http"),
// The HPackEncoder will encode £ as 0xA3 aka Latin1 encoding.
new KeyValuePair<string, string>("X-Test", "£"),
};
await InitializeConnectionAsync(_noopApplication);
await StartStreamAsync(1, headers, endStream: true);
await StartStreamAsync(1, LatinHeaderData, endStream: true);
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
ignoreNonGoAwayFrames: true,

View File

@ -119,7 +119,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
private readonly MemoryPool<byte> _memoryPool = SlabMemoryPoolFactory.Create();
internal readonly Http2PeerSettings _clientSettings = new Http2PeerSettings();
internal readonly HPackEncoder _hpackEncoder = new HPackEncoder();
internal readonly HPackDecoder _hpackDecoder;
private readonly byte[] _headerEncodingBuffer = new byte[Http2PeerSettings.MinAllowedMaxFrameSize];
@ -501,7 +500,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
_runningStreams[streamId] = tcs;
PipeWriterHttp2FrameExtensions.WriteStartStream(writableBuffer, streamId, GetHeadersEnumerator(headers), _hpackEncoder, _headerEncodingBuffer, endStream);
writableBuffer.WriteStartStream(streamId, GetHeadersEnumerator(headers), _headerEncodingBuffer, endStream);
return FlushAsync(writableBuffer);
}
protected Task StartStreamAsync(int streamId, Span<byte> headerData, bool endStream)
{
var writableBuffer = _pair.Application.Output;
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
_runningStreams[streamId] = tcs;
writableBuffer.WriteStartStream(streamId, headerData, endStream);
return FlushAsync(writableBuffer);
}
@ -531,7 +540,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[0] = padLength;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
_hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -574,7 +583,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[4] = priority;
var payload = buffer.Slice(extendedHeaderLength);
_hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
frame.PayloadLength = extendedHeaderLength + length;
@ -621,7 +630,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
extendedHeader[5] = priority;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
_hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -658,7 +667,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
protected async Task SendSettingsAsync()
{
PipeWriterHttp2FrameExtensions.WriteSettings(_pair.Application.Output, _clientSettings);
_pair.Application.Output.WriteSettings(_clientSettings);
await FlushAsync(_pair.Application.Output);
}
@ -728,14 +737,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
return FlushAsync(writableBuffer);
}
internal async Task<bool> SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, IEnumerable<KeyValuePair<string, string>> headers)
internal async Task<bool> SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, Http2HeadersEnumerator headersEnumerator)
{
var outputWriter = _pair.Application.Output;
var frame = new Http2Frame();
frame.PrepareHeaders(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(headersEnumerator, buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);
@ -744,6 +753,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
return done;
}
internal Task<bool> SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, IEnumerable<KeyValuePair<string, string>> headers)
{
return SendHeadersAsync(streamId, flags, GetHeadersEnumerator(headers));
}
internal async Task SendHeadersAsync(int streamId, Http2HeadersFrameFlags flags, byte[] headerBlock)
{
var outputWriter = _pair.Application.Output;
@ -793,14 +807,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendAsync(payload);
}
internal async Task<bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags)
internal async Task<bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, Http2HeadersEnumerator headersEnumerator)
{
var outputWriter = _pair.Application.Output;
var frame = new Http2Frame();
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.Encode(buffer.Span, out var length);
var done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);
@ -828,7 +842,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.BeginEncode(GetHeadersEnumerator(headers), buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), buffer.Span, out var length);
frame.PayloadLength = length;
Http2FrameWriter.WriteHeader(frame, outputWriter);
@ -837,7 +851,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
return done;
}
private Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
internal Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
{
var dictionary = headers
.GroupBy(g => g.Key)
@ -881,7 +895,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
protected Task SendDataAsync(int streamId, Memory<byte> data, bool endStream)
{
var outputWriter = _pair.Application.Output;
PipeWriterHttp2FrameExtensions.WriteData(outputWriter, streamId, data, endStream);
outputWriter.WriteData(streamId, data, endStream);
return FlushAsync(outputWriter);
}

View File

@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_mockTimeoutControl.Verify(c => c.SetTimeout(It.IsAny<long>(), TimeoutReason.RequestHeaders), Times.Once);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);
@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -390,7 +390,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -444,7 +444,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -500,7 +500,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
@ -512,7 +512,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -566,7 +566,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -615,7 +615,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -668,7 +668,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -681,7 +681,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -737,7 +737,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -755,7 +755,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -812,7 +812,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(1, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 1);
@ -884,7 +884,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await SendDataAsync(3, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 37,
withLength: 33,
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
@ -901,7 +901,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
backpressureTcs.SetResult(null);
await ExpectAsync(Http2FrameType.HEADERS,
withLength: 55,
withLength: 37,
withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM),
withStreamId: 1);

View File

@ -1118,7 +1118,7 @@ namespace Interop.FunctionalTests
Assert.Equal(oneKbString + i, response.Headers.GetValues("header" + i).Single());
}
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending HEADERS frame for stream ID 1 with length 15636 and flags END_STREAM")));
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending HEADERS frame for stream ID 1 with length 15612 and flags END_STREAM")));
Assert.Equal(2, TestSink.Writes.Where(context => context.Message.Contains("sending CONTINUATION frame for stream ID 1 with length 15585 and flags NONE")).Count());
Assert.Single(TestSink.Writes.Where(context => context.Message.Contains("sending CONTINUATION frame for stream ID 1 with length 14546 and flags END_HEADERS")));

View File

@ -0,0 +1,91 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.HPack;
namespace Microsoft.AspNetCore.Http2Cat
{
internal static class HPackHeaderWriter
{
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(int statusCode, IEnumerator<KeyValuePair<string, string>> headersEnumerator, Span<byte> buffer, out int length)
{
if (!HPackEncoder.EncodeStatusHeader(statusCode, buffer, out var statusCodeLength))
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
if (!headersEnumerator.MoveNext())
{
length = statusCodeLength;
return true;
}
// We're ok with not throwing if no headers were encoded because we've already encoded the status.
// There is a small chance that the header will encode if there is no other content in the next HEADERS frame.
var done = EncodeHeaders(headersEnumerator, buffer.Slice(statusCodeLength), throwIfNoneEncoded: false, out var headersLength);
length = statusCodeLength + headersLength;
return done;
}
/// <summary>
/// Begin encoding headers in the first HEADERS frame.
/// </summary>
public static bool BeginEncodeHeaders(IEnumerator<KeyValuePair<string, string>> headersEnumerator, Span<byte> buffer, out int length)
{
if (!headersEnumerator.MoveNext())
{
length = 0;
return true;
}
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
}
/// <summary>
/// Continue encoding headers in the next HEADERS frame. The enumerator should already have a current value.
/// </summary>
public static bool ContinueEncodeHeaders(IEnumerator<KeyValuePair<string, string>> headersEnumerator, Span<byte> buffer, out int length)
{
return EncodeHeaders(headersEnumerator, buffer, throwIfNoneEncoded: true, out length);
}
private static bool EncodeHeaders(IEnumerator<KeyValuePair<string, string>> headersEnumerator, Span<byte> buffer, bool throwIfNoneEncoded, out int length)
{
var currentLength = 0;
do
{
if (!EncodeHeader(headersEnumerator.Current.Key, headersEnumerator.Current.Value, buffer.Slice(currentLength), out int headerLength))
{
// The the header wasn't written and no headers have been written then the header is too large.
// Throw an error to avoid an infinite loop of attempting to write large header.
if (currentLength == 0 && throwIfNoneEncoded)
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length = currentLength;
return false;
}
currentLength += headerLength;
}
while (headersEnumerator.MoveNext());
length = currentLength;
return true;
}
private static bool EncodeHeader(string name, string value, Span<byte> buffer, out int length)
{
return HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, buffer, out length);
}
}
}

View File

@ -122,7 +122,6 @@ namespace Microsoft.AspNetCore.Http2Cat
public static readonly byte[] _maxData = Encoding.ASCII.GetBytes(new string('a', Http2PeerSettings.MinAllowedMaxFrameSize));
internal readonly Http2PeerSettings _clientSettings = new Http2PeerSettings();
internal readonly HPackEncoder _hpackEncoder = new HPackEncoder();
internal readonly HPackDecoder _hpackDecoder;
private readonly byte[] _headerEncodingBuffer = new byte[Http2PeerSettings.MinAllowedMaxFrameSize];
@ -236,7 +235,8 @@ namespace Microsoft.AspNetCore.Http2Cat
frame.PrepareHeaders(Http2HeadersFrameFlags.NONE, streamId);
var buffer = _headerEncodingBuffer.AsSpan();
var done = _hpackEncoder.BeginEncode(headers.GetEnumerator(), buffer, out var length);
var headersEnumerator = GetHeadersEnumerator(headers);
var done = HPackHeaderWriter.BeginEncodeHeaders(headersEnumerator, buffer, out var length);
frame.PayloadLength = length;
if (done)
@ -256,7 +256,7 @@ namespace Microsoft.AspNetCore.Http2Cat
{
frame.PrepareContinuation(Http2ContinuationFrameFlags.NONE, streamId);
done = _hpackEncoder.Encode(buffer, out length);
done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer, out length);
frame.PayloadLength = length;
if (done)
@ -271,6 +271,12 @@ namespace Microsoft.AspNetCore.Http2Cat
return FlushAsync(writableBuffer);
}
private static IEnumerator<KeyValuePair<string, string>> GetHeadersEnumerator(IEnumerable<KeyValuePair<string, string>> headers)
{
var headersEnumerator = headers.GetEnumerator();
return headersEnumerator;
}
internal Dictionary<string, string> DecodeHeaders(Http2FrameWithPayload frame, bool endHeaders = false)
{
Assert.Equal(Http2FrameType.HEADERS, frame.Type);
@ -335,7 +341,7 @@ namespace Microsoft.AspNetCore.Http2Cat
extendedHeader[0] = padLength;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
_hpackEncoder.BeginEncode(headers.GetEnumerator(), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -377,7 +383,7 @@ namespace Microsoft.AspNetCore.Http2Cat
extendedHeader[4] = priority;
var payload = buffer.Slice(extendedHeaderLength);
_hpackEncoder.BeginEncode(headers.GetEnumerator(), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
frame.PayloadLength = extendedHeaderLength + length;
@ -423,7 +429,7 @@ namespace Microsoft.AspNetCore.Http2Cat
extendedHeader[5] = priority;
var payload = buffer.Slice(extendedHeaderLength, buffer.Length - padLength - extendedHeaderLength);
_hpackEncoder.BeginEncode(headers.GetEnumerator(), payload, out var length);
HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), payload, out var length);
var padding = buffer.Slice(extendedHeaderLength + length, padLength);
padding.Fill(0);
@ -549,7 +555,7 @@ namespace Microsoft.AspNetCore.Http2Cat
frame.PrepareHeaders(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.BeginEncode(headers.GetEnumerator(), buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), buffer.Span, out var length);
frame.PayloadLength = length;
WriteHeader(frame, outputWriter);
@ -607,14 +613,14 @@ namespace Microsoft.AspNetCore.Http2Cat
await SendAsync(payload);
}
internal async Task<bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags)
internal async Task<bool> SendContinuationAsync(int streamId, Http2ContinuationFrameFlags flags, IEnumerator<KeyValuePair<string, string>> headersEnumerator)
{
var outputWriter = _pair.Application.Output;
var frame = new Http2Frame();
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.Encode(buffer.Span, out var length);
var done = HPackHeaderWriter.ContinueEncodeHeaders(headersEnumerator, buffer.Span, out var length);
frame.PayloadLength = length;
WriteHeader(frame, outputWriter);
@ -642,7 +648,7 @@ namespace Microsoft.AspNetCore.Http2Cat
frame.PrepareContinuation(flags, streamId);
var buffer = _headerEncodingBuffer.AsMemory();
var done = _hpackEncoder.BeginEncode(headers.GetEnumerator(), buffer.Span, out var length);
var done = HPackHeaderWriter.BeginEncodeHeaders(GetHeadersEnumerator(headers), buffer.Span, out var length);
frame.PayloadLength = length;
WriteHeader(frame, outputWriter);

View File

@ -108,6 +108,7 @@ namespace System.Net.Http.HPack
public const int PathSlash = 4;
public const int SchemeHttp = 6;
public const int SchemeHttps = 7;
public const int Status200 = 8;
public const int AcceptCharset = 15;
public const int AcceptEncoding = 16;
public const int AcceptLanguage = 17;

View File

@ -3,172 +3,11 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
#if KESTREL
using HeadersEnumerator = Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2HeadersEnumerator;
#else
using HeadersEnumerator = System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, string>>;
#endif
namespace System.Net.Http.HPack
{
internal class HPackEncoder
internal static class HPackEncoder
{
private HeadersEnumerator _enumerator;
public bool BeginEncode(HeadersEnumerator enumerator, Span<byte> buffer, out int length)
{
_enumerator = enumerator;
_enumerator.MoveNext();
return Encode(buffer, out length);
}
public bool BeginEncode(int statusCode, HeadersEnumerator enumerator, Span<byte> buffer, out int length)
{
_enumerator = enumerator;
_enumerator.MoveNext();
int statusCodeLength = EncodeStatusCode(statusCode, buffer);
bool done = Encode(buffer.Slice(statusCodeLength), throwIfNoneEncoded: false, out int headersLength);
length = statusCodeLength + headersLength;
return done;
}
public bool Encode(Span<byte> buffer, out int length)
{
return Encode(buffer, throwIfNoneEncoded: true, out length);
}
private bool Encode(Span<byte> buffer, bool throwIfNoneEncoded, out int length)
{
int currentLength = 0;
do
{
if (!EncodeHeader(_enumerator.Current.Key, _enumerator.Current.Value, buffer.Slice(currentLength), out int headerLength))
{
if (currentLength == 0 && throwIfNoneEncoded)
{
throw new HPackEncodingException(SR.net_http_hpack_encode_failure);
}
length = currentLength;
return false;
}
currentLength += headerLength;
}
while (_enumerator.MoveNext());
length = currentLength;
return true;
}
private int EncodeStatusCode(int statusCode, Span<byte> buffer)
{
switch (statusCode)
{
// Status codes which exist in the HTTP/2 StaticTable.
case 200:
case 204:
case 206:
case 304:
case 400:
case 404:
case 500:
buffer[0] = (byte)(0x80 | H2StaticTable.StatusIndex[statusCode]);
return 1;
default:
// Send as Literal Header Field Without Indexing - Indexed Name
buffer[0] = 0x08;
ReadOnlySpan<byte> statusBytes = StatusCodes.ToStatusBytes(statusCode);
buffer[1] = (byte)statusBytes.Length;
statusBytes.CopyTo(buffer.Slice(2));
return 2 + statusBytes.Length;
}
}
private bool EncodeHeader(string name, string value, Span<byte> buffer, out int length)
{
int i = 0;
length = 0;
if (buffer.Length == 0)
{
return false;
}
buffer[i++] = 0;
if (i == buffer.Length)
{
return false;
}
if (!EncodeString(name, buffer.Slice(i), out int nameLength, lowercase: true))
{
return false;
}
i += nameLength;
if (i >= buffer.Length)
{
return false;
}
if (!EncodeString(value, buffer.Slice(i), out int valueLength, lowercase: false))
{
return false;
}
i += valueLength;
length = i;
return true;
}
private bool EncodeString(string value, Span<byte> destination, out int bytesWritten, bool lowercase)
{
// From https://tools.ietf.org/html/rfc7541#section-5.2
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | H | String Length (7+) |
// +---+---------------------------+
// | String Data (Length octets) |
// +-------------------------------+
const int toLowerMask = 0x20;
if (destination.Length != 0)
{
destination[0] = 0; // TODO: Use Huffman encoding
if (IntegerEncoder.Encode(value.Length, 7, destination, out int integerLength))
{
Debug.Assert(integerLength >= 1);
destination = destination.Slice(integerLength);
if (value.Length <= destination.Length)
{
for (int i = 0; i < value.Length; i++)
{
char c = value[i];
destination[i] = (byte)(lowercase && (uint)(c - 'A') <= ('Z' - 'A') ? c | toLowerMask : c);
}
bytesWritten = integerLength + value.Length;
return true;
}
}
}
bytesWritten = 0;
return false;
}
// Things we should add:
// * Huffman encoding
//
@ -199,6 +38,43 @@ namespace System.Net.Http.HPack
return false;
}
/// <summary>Encodes the status code of a response to the :status field.</summary>
public static bool EncodeStatusHeader(int statusCode, Span<byte> destination, out int bytesWritten)
{
// Bytes written depend on whether the status code value maps directly to an index
switch (statusCode)
{
case 200:
case 204:
case 206:
case 304:
case 400:
case 404:
case 500:
// Status codes which exist in the HTTP/2 StaticTable.
return EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], destination, out bytesWritten);
default:
// If the status code doesn't have a static index then we need to include the full value.
// Write a status index and then the number bytes as a string literal.
if (!EncodeLiteralHeaderFieldWithoutIndexing(H2StaticTable.Status200, destination, out var nameLength))
{
bytesWritten = 0;
return false;
}
var statusBytes = StatusCodes.ToStatusBytes(statusCode);
if (!EncodeStringLiteral(statusBytes, destination.Slice(nameLength), out var valueLength))
{
bytesWritten = 0;
return false;
}
bytesWritten = nameLength + valueLength;
return true;
}
}
/// <summary>Encodes a "Literal Header Field without Indexing".</summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexing(int index, string value, Span<byte> destination, out int bytesWritten)
{
@ -233,7 +109,7 @@ namespace System.Net.Http.HPack
/// <summary>
/// Encodes a "Literal Header Field without Indexing", but only the index portion;
/// a subsequent call to <see cref="EncodeStringLiteral"/> must be used to encode the associated value.
/// a subsequent call to <c>EncodeStringLiteral</c> must be used to encode the associated value.
/// </summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexing(int index, Span<byte> destination, out int bytesWritten)
{
@ -266,6 +142,39 @@ namespace System.Net.Http.HPack
return false;
}
/// <summary>Encodes a "Literal Header Field without Indexing - New Name".</summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexingNewName(string name, string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-6.2.2
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | 0 | 0 | 0 | 0 | 0 |
// +---+---+-----------------------+
// | H | Name Length (7+) |
// +---+---------------------------+
// | Name String (Length octets) |
// +---+---------------------------+
// | H | Value Length (7+) |
// +---+---------------------------+
// | Value String (Length octets) |
// +-------------------------------+
if ((uint)destination.Length >= 3)
{
destination[0] = 0;
if (EncodeLiteralHeaderName(name, destination.Slice(1), out int nameLength) &&
EncodeStringLiteral(value, destination.Slice(1 + nameLength), out int valueLength))
{
bytesWritten = 1 + nameLength + valueLength;
return true;
}
}
bytesWritten = 0;
return false;
}
/// <summary>Encodes a "Literal Header Field without Indexing - New Name".</summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexingNewName(string name, ReadOnlySpan<string> values, string separator, Span<byte> destination, out int bytesWritten)
{
@ -301,7 +210,7 @@ namespace System.Net.Http.HPack
/// <summary>
/// Encodes a "Literal Header Field without Indexing - New Name", but only the name portion;
/// a subsequent call to <see cref="EncodeStringLiteral"/> must be used to encode the associated value.
/// a subsequent call to <c>EncodeStringLiteral</c> must be used to encode the associated value.
/// </summary>
public static bool EncodeLiteralHeaderFieldWithoutIndexingNewName(string name, Span<byte> destination, out int bytesWritten)
{
@ -397,6 +306,40 @@ namespace System.Net.Http.HPack
return false;
}
public static bool EncodeStringLiteral(ReadOnlySpan<byte> value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-5.2
// ------------------------------------------------------
// 0 1 2 3 4 5 6 7
// +---+---+---+---+---+---+---+---+
// | H | String Length (7+) |
// +---+---------------------------+
// | String Data (Length octets) |
// +-------------------------------+
if (destination.Length != 0)
{
destination[0] = 0; // TODO: Use Huffman encoding
if (IntegerEncoder.Encode(value.Length, 7, destination, out int integerLength))
{
Debug.Assert(integerLength >= 1);
destination = destination.Slice(integerLength);
if (value.Length <= destination.Length)
{
// Note: No validation. Bytes should have already been validated.
value.CopyTo(destination);
bytesWritten = integerLength + value.Length;
return true;
}
}
}
bytesWritten = 0;
return false;
}
public static bool EncodeStringLiteral(string value, Span<byte> destination, out int bytesWritten)
{
// From https://tools.ietf.org/html/rfc7541#section-5.2
@ -485,7 +428,7 @@ namespace System.Net.Http.HPack
/// <summary>
/// Encodes a "Literal Header Field without Indexing" to a new array, but only the index portion;
/// a subsequent call to <see cref="EncodeStringLiteral"/> must be used to encode the associated value.
/// a subsequent call to <c>EncodeStringLiteral</c> must be used to encode the associated value.
/// </summary>
public static byte[] EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(int index)
{
@ -497,7 +440,7 @@ namespace System.Net.Http.HPack
/// <summary>
/// Encodes a "Literal Header Field without Indexing - New Name" to a new array, but only the name portion;
/// a subsequent call to <see cref="EncodeStringLiteral"/> must be used to encode the associated value.
/// a subsequent call to <c>EncodeStringLiteral</c> must be used to encode the associated value.
/// </summary>
public static byte[] EncodeLiteralHeaderFieldWithoutIndexingNewNameToAllocatedArray(string name)
{