From 8a86e0fab026ad3cab5d10305d79d81776f2e0ff Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sat, 24 Feb 2018 19:15:48 +0000 Subject: [PATCH 1/6] Less StringValue struct copies for header checks --- .../Internal/Http/Http1MessageBody.cs | 11 +- .../Internal/Http/HttpHeaders.Generated.cs | 567 +++++++++++++----- src/Kestrel.Core/Internal/Http/HttpHeaders.cs | 9 +- .../Internal/Http/HttpProtocol.cs | 4 +- .../Internal/Http/HttpResponseHeaders.cs | 8 - tools/CodeGenerator/KnownHeaders.cs | 37 +- 6 files changed, 455 insertions(+), 181 deletions(-) diff --git a/src/Kestrel.Core/Internal/Http/Http1MessageBody.cs b/src/Kestrel.Core/Internal/Http/Http1MessageBody.cs index 5ac13c69a..f6e66c245 100644 --- a/src/Kestrel.Core/Internal/Http/Http1MessageBody.cs +++ b/src/Kestrel.Core/Internal/Http/Http1MessageBody.cs @@ -213,11 +213,10 @@ public static MessageBody For( // see also http://tools.ietf.org/html/rfc2616#section-4.4 var keepAlive = httpVersion != HttpVersion.Http10; - var connection = headers.HeaderConnection; var upgrade = false; - if (connection.Count > 0) + if (headers.HasConnection) { - var connectionOptions = HttpHeaders.ParseConnection(connection); + var connectionOptions = HttpHeaders.ParseConnection(headers.HeaderConnection); upgrade = (connectionOptions & ConnectionOptions.Upgrade) == ConnectionOptions.Upgrade; keepAlive = (connectionOptions & ConnectionOptions.KeepAlive) == ConnectionOptions.KeepAlive; @@ -233,10 +232,10 @@ public static MessageBody For( return new ForUpgrade(context); } - var transferEncoding = headers.HeaderTransferEncoding; - if (transferEncoding.Count > 0) + if (headers.HasTransferEncoding) { - var transferCoding = HttpHeaders.GetFinalTransferCoding(headers.HeaderTransferEncoding); + var transferEncoding = headers.HeaderTransferEncoding; + var transferCoding = HttpHeaders.GetFinalTransferCoding(transferEncoding); // https://tools.ietf.org/html/rfc7230#section-3.3.3 // If a Transfer-Encoding header field diff --git a/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs b/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs index 27473181b..5704b85ae 100644 --- a/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs +++ b/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs @@ -17,6 +17,11 @@ public partial class HttpRequestHeaders private long _bits = 0; private HeaderReferences _headers; + + public bool HasConnection => (_bits & 2L) != 0; + public bool HasTransferEncoding => (_bits & 64L) != 0; + + public int HostCount => _headers._Host.Count; public StringValues HeaderCacheControl { @@ -1602,6 +1607,7 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) { + var isNotNull = value.Count > 0; switch (key.Length) { case 13: @@ -1610,8 +1616,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1L) == 0) { - _bits |= 1L; - _headers._CacheControl = value; + if (isNotNull) + { + _bits |= 1L; + _headers._CacheControl = value; + } return true; } return false; @@ -1620,8 +1629,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 65536L) == 0) { - _bits |= 65536L; - _headers._ContentRange = value; + if (isNotNull) + { + _bits |= 65536L; + _headers._ContentRange = value; + } return true; } return false; @@ -1630,8 +1642,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 262144L) == 0) { - _bits |= 262144L; - _headers._LastModified = value; + if (isNotNull) + { + _bits |= 262144L; + _headers._LastModified = value; + } return true; } return false; @@ -1640,8 +1655,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8388608L) == 0) { - _bits |= 8388608L; - _headers._Authorization = value; + if (isNotNull) + { + _bits |= 8388608L; + _headers._Authorization = value; + } return true; } return false; @@ -1650,8 +1668,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1073741824L) == 0) { - _bits |= 1073741824L; - _headers._IfNoneMatch = value; + if (isNotNull) + { + _bits |= 1073741824L; + _headers._IfNoneMatch = value; + } return true; } return false; @@ -1664,8 +1685,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2L) == 0) { - _bits |= 2L; - _headers._Connection = value; + if (isNotNull) + { + _bits |= 2L; + _headers._Connection = value; + } return true; } return false; @@ -1674,8 +1698,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8L) == 0) { - _bits |= 8L; - _headers._KeepAlive = value; + if (isNotNull) + { + _bits |= 8L; + _headers._KeepAlive = value; + } return true; } return false; @@ -1684,8 +1711,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 549755813888L) == 0) { - _bits |= 549755813888L; - _headers._UserAgent = value; + if (isNotNull) + { + _bits |= 549755813888L; + _headers._UserAgent = value; + } return true; } return false; @@ -1698,8 +1728,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4L) == 0) { - _bits |= 4L; - _headers._Date = value; + if (isNotNull) + { + _bits |= 4L; + _headers._Date = value; + } return true; } return false; @@ -1708,8 +1741,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 67108864L) == 0) { - _bits |= 67108864L; - _headers._From = value; + if (isNotNull) + { + _bits |= 67108864L; + _headers._From = value; + } return true; } return false; @@ -1718,8 +1754,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 134217728L) == 0) { - _bits |= 134217728L; - _headers._Host = value; + if (isNotNull) + { + _bits |= 134217728L; + _headers._Host = value; + } return true; } return false; @@ -1732,8 +1771,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16L) == 0) { - _bits |= 16L; - _headers._Pragma = value; + if (isNotNull) + { + _bits |= 16L; + _headers._Pragma = value; + } return true; } return false; @@ -1742,8 +1784,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 524288L) == 0) { - _bits |= 524288L; - _headers._Accept = value; + if (isNotNull) + { + _bits |= 524288L; + _headers._Accept = value; + } return true; } return false; @@ -1752,8 +1797,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16777216L) == 0) { - _bits |= 16777216L; - _headers._Cookie = value; + if (isNotNull) + { + _bits |= 16777216L; + _headers._Cookie = value; + } return true; } return false; @@ -1762,8 +1810,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 33554432L) == 0) { - _bits |= 33554432L; - _headers._Expect = value; + if (isNotNull) + { + _bits |= 33554432L; + _headers._Expect = value; + } return true; } return false; @@ -1772,8 +1823,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1099511627776L) == 0) { - _bits |= 1099511627776L; - _headers._Origin = value; + if (isNotNull) + { + _bits |= 1099511627776L; + _headers._Origin = value; + } return true; } return false; @@ -1786,8 +1840,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32L) == 0) { - _bits |= 32L; - _headers._Trailer = value; + if (isNotNull) + { + _bits |= 32L; + _headers._Trailer = value; + } return true; } return false; @@ -1796,8 +1853,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 128L) == 0) { - _bits |= 128L; - _headers._Upgrade = value; + if (isNotNull) + { + _bits |= 128L; + _headers._Upgrade = value; + } return true; } return false; @@ -1806,8 +1866,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 512L) == 0) { - _bits |= 512L; - _headers._Warning = value; + if (isNotNull) + { + _bits |= 512L; + _headers._Warning = value; + } return true; } return false; @@ -1816,8 +1879,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 131072L) == 0) { - _bits |= 131072L; - _headers._Expires = value; + if (isNotNull) + { + _bits |= 131072L; + _headers._Expires = value; + } return true; } return false; @@ -1826,8 +1892,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 34359738368L) == 0) { - _bits |= 34359738368L; - _headers._Referer = value; + if (isNotNull) + { + _bits |= 34359738368L; + _headers._Referer = value; + } return true; } return false; @@ -1840,8 +1909,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 64L) == 0) { - _bits |= 64L; - _headers._TransferEncoding = value; + if (isNotNull) + { + _bits |= 64L; + _headers._TransferEncoding = value; + } return true; } return false; @@ -1850,8 +1922,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 536870912L) == 0) { - _bits |= 536870912L; - _headers._IfModifiedSince = value; + if (isNotNull) + { + _bits |= 536870912L; + _headers._IfModifiedSince = value; + } return true; } return false; @@ -1864,8 +1939,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 256L) == 0) { - _bits |= 256L; - _headers._Via = value; + if (isNotNull) + { + _bits |= 256L; + _headers._Via = value; + } return true; } return false; @@ -1878,8 +1956,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1024L) == 0) { - _bits |= 1024L; - _headers._Allow = value; + if (isNotNull) + { + _bits |= 1024L; + _headers._Allow = value; + } return true; } return false; @@ -1888,8 +1969,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 68719476736L) == 0) { - _bits |= 68719476736L; - _headers._Range = value; + if (isNotNull) + { + _bits |= 68719476736L; + _headers._Range = value; + } return true; } return false; @@ -1902,8 +1986,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2048L) == 0) { - _bits |= 2048L; - _headers._ContentType = value; + if (isNotNull) + { + _bits |= 2048L; + _headers._ContentType = value; + } return true; } return false; @@ -1912,8 +1999,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8589934592L) == 0) { - _bits |= 8589934592L; - _headers._MaxForwards = value; + if (isNotNull) + { + _bits |= 8589934592L; + _headers._MaxForwards = value; + } return true; } return false; @@ -1926,8 +2016,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4096L) == 0) { - _bits |= 4096L; - _headers._ContentEncoding = value; + if (isNotNull) + { + _bits |= 4096L; + _headers._ContentEncoding = value; + } return true; } return false; @@ -1936,8 +2029,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8192L) == 0) { - _bits |= 8192L; - _headers._ContentLanguage = value; + if (isNotNull) + { + _bits |= 8192L; + _headers._ContentLanguage = value; + } return true; } return false; @@ -1946,8 +2042,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16384L) == 0) { - _bits |= 16384L; - _headers._ContentLocation = value; + if (isNotNull) + { + _bits |= 16384L; + _headers._ContentLocation = value; + } return true; } return false; @@ -1960,8 +2059,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32768L) == 0) { - _bits |= 32768L; - _headers._ContentMD5 = value; + if (isNotNull) + { + _bits |= 32768L; + _headers._ContentMD5 = value; + } return true; } return false; @@ -1974,8 +2076,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1048576L) == 0) { - _bits |= 1048576L; - _headers._AcceptCharset = value; + if (isNotNull) + { + _bits |= 1048576L; + _headers._AcceptCharset = value; + } return true; } return false; @@ -1997,8 +2102,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2097152L) == 0) { - _bits |= 2097152L; - _headers._AcceptEncoding = value; + if (isNotNull) + { + _bits |= 2097152L; + _headers._AcceptEncoding = value; + } return true; } return false; @@ -2007,8 +2115,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4194304L) == 0) { - _bits |= 4194304L; - _headers._AcceptLanguage = value; + if (isNotNull) + { + _bits |= 4194304L; + _headers._AcceptLanguage = value; + } return true; } return false; @@ -2021,8 +2132,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 268435456L) == 0) { - _bits |= 268435456L; - _headers._IfMatch = value; + if (isNotNull) + { + _bits |= 268435456L; + _headers._IfMatch = value; + } return true; } return false; @@ -2031,8 +2145,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2147483648L) == 0) { - _bits |= 2147483648L; - _headers._IfRange = value; + if (isNotNull) + { + _bits |= 2147483648L; + _headers._IfRange = value; + } return true; } return false; @@ -2045,8 +2162,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4294967296L) == 0) { - _bits |= 4294967296L; - _headers._IfUnmodifiedSince = value; + if (isNotNull) + { + _bits |= 4294967296L; + _headers._IfUnmodifiedSince = value; + } return true; } return false; @@ -2055,8 +2175,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 17179869184L) == 0) { - _bits |= 17179869184L; - _headers._ProxyAuthorization = value; + if (isNotNull) + { + _bits |= 17179869184L; + _headers._ProxyAuthorization = value; + } return true; } return false; @@ -2069,8 +2192,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 137438953472L) == 0) { - _bits |= 137438953472L; - _headers._TE = value; + if (isNotNull) + { + _bits |= 137438953472L; + _headers._TE = value; + } return true; } return false; @@ -2083,8 +2209,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 274877906944L) == 0) { - _bits |= 274877906944L; - _headers._Translate = value; + if (isNotNull) + { + _bits |= 274877906944L; + _headers._Translate = value; + } return true; } return false; @@ -2097,8 +2226,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2199023255552L) == 0) { - _bits |= 2199023255552L; - _headers._AccessControlRequestMethod = value; + if (isNotNull) + { + _bits |= 2199023255552L; + _headers._AccessControlRequestMethod = value; + } return true; } return false; @@ -2111,8 +2243,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4398046511104L) == 0) { - _bits |= 4398046511104L; - _headers._AccessControlRequestHeaders = value; + if (isNotNull) + { + _bits |= 4398046511104L; + _headers._AccessControlRequestHeaders = value; + } return true; } return false; @@ -4794,6 +4929,12 @@ public partial class HttpResponseHeaders private long _bits = 0; private HeaderReferences _headers; + + public bool HasConnection => (_bits & 2L) != 0; + public bool HasDate => (_bits & 4L) != 0; + public bool HasTransferEncoding => (_bits & 64L) != 0; + public bool HasServer => (_bits & 33554432L) != 0; + public StringValues HeaderCacheControl { @@ -6157,6 +6298,7 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) { ValidateHeaderCharacters(value); + var isNotNull = value.Count > 0; switch (key.Length) { case 13: @@ -6165,8 +6307,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1L) == 0) { - _bits |= 1L; - _headers._CacheControl = value; + if (isNotNull) + { + _bits |= 1L; + _headers._CacheControl = value; + } return true; } return false; @@ -6175,8 +6320,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 65536L) == 0) { - _bits |= 65536L; - _headers._ContentRange = value; + if (isNotNull) + { + _bits |= 65536L; + _headers._ContentRange = value; + } return true; } return false; @@ -6185,8 +6333,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 262144L) == 0) { - _bits |= 262144L; - _headers._LastModified = value; + if (isNotNull) + { + _bits |= 262144L; + _headers._LastModified = value; + } return true; } return false; @@ -6195,8 +6346,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 524288L) == 0) { - _bits |= 524288L; - _headers._AcceptRanges = value; + if (isNotNull) + { + _bits |= 524288L; + _headers._AcceptRanges = value; + } return true; } return false; @@ -6209,9 +6363,12 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2L) == 0) { - _bits |= 2L; - _headers._Connection = value; - _headers._rawConnection = null; + if (isNotNull) + { + _bits |= 2L; + _headers._Connection = value; + _headers._rawConnection = null; + } return true; } return false; @@ -6220,8 +6377,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8L) == 0) { - _bits |= 8L; - _headers._KeepAlive = value; + if (isNotNull) + { + _bits |= 8L; + _headers._KeepAlive = value; + } return true; } return false; @@ -6230,8 +6390,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 67108864L) == 0) { - _bits |= 67108864L; - _headers._SetCookie = value; + if (isNotNull) + { + _bits |= 67108864L; + _headers._SetCookie = value; + } return true; } return false; @@ -6244,9 +6407,12 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4L) == 0) { - _bits |= 4L; - _headers._Date = value; - _headers._rawDate = null; + if (isNotNull) + { + _bits |= 4L; + _headers._Date = value; + _headers._rawDate = null; + } return true; } return false; @@ -6255,8 +6421,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2097152L) == 0) { - _bits |= 2097152L; - _headers._ETag = value; + if (isNotNull) + { + _bits |= 2097152L; + _headers._ETag = value; + } return true; } return false; @@ -6265,8 +6434,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 134217728L) == 0) { - _bits |= 134217728L; - _headers._Vary = value; + if (isNotNull) + { + _bits |= 134217728L; + _headers._Vary = value; + } return true; } return false; @@ -6279,8 +6451,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16L) == 0) { - _bits |= 16L; - _headers._Pragma = value; + if (isNotNull) + { + _bits |= 16L; + _headers._Pragma = value; + } return true; } return false; @@ -6289,9 +6464,12 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 33554432L) == 0) { - _bits |= 33554432L; - _headers._Server = value; - _headers._rawServer = null; + if (isNotNull) + { + _bits |= 33554432L; + _headers._Server = value; + _headers._rawServer = null; + } return true; } return false; @@ -6304,8 +6482,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32L) == 0) { - _bits |= 32L; - _headers._Trailer = value; + if (isNotNull) + { + _bits |= 32L; + _headers._Trailer = value; + } return true; } return false; @@ -6314,8 +6495,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 128L) == 0) { - _bits |= 128L; - _headers._Upgrade = value; + if (isNotNull) + { + _bits |= 128L; + _headers._Upgrade = value; + } return true; } return false; @@ -6324,8 +6508,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 512L) == 0) { - _bits |= 512L; - _headers._Warning = value; + if (isNotNull) + { + _bits |= 512L; + _headers._Warning = value; + } return true; } return false; @@ -6334,8 +6521,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 131072L) == 0) { - _bits |= 131072L; - _headers._Expires = value; + if (isNotNull) + { + _bits |= 131072L; + _headers._Expires = value; + } return true; } return false; @@ -6348,9 +6538,12 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 64L) == 0) { - _bits |= 64L; - _headers._TransferEncoding = value; - _headers._rawTransferEncoding = null; + if (isNotNull) + { + _bits |= 64L; + _headers._TransferEncoding = value; + _headers._rawTransferEncoding = null; + } return true; } return false; @@ -6363,8 +6556,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 256L) == 0) { - _bits |= 256L; - _headers._Via = value; + if (isNotNull) + { + _bits |= 256L; + _headers._Via = value; + } return true; } return false; @@ -6373,8 +6569,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1048576L) == 0) { - _bits |= 1048576L; - _headers._Age = value; + if (isNotNull) + { + _bits |= 1048576L; + _headers._Age = value; + } return true; } return false; @@ -6387,8 +6586,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1024L) == 0) { - _bits |= 1024L; - _headers._Allow = value; + if (isNotNull) + { + _bits |= 1024L; + _headers._Allow = value; + } return true; } return false; @@ -6401,8 +6603,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2048L) == 0) { - _bits |= 2048L; - _headers._ContentType = value; + if (isNotNull) + { + _bits |= 2048L; + _headers._ContentType = value; + } return true; } return false; @@ -6415,8 +6620,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4096L) == 0) { - _bits |= 4096L; - _headers._ContentEncoding = value; + if (isNotNull) + { + _bits |= 4096L; + _headers._ContentEncoding = value; + } return true; } return false; @@ -6425,8 +6633,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8192L) == 0) { - _bits |= 8192L; - _headers._ContentLanguage = value; + if (isNotNull) + { + _bits |= 8192L; + _headers._ContentLanguage = value; + } return true; } return false; @@ -6435,8 +6646,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16384L) == 0) { - _bits |= 16384L; - _headers._ContentLocation = value; + if (isNotNull) + { + _bits |= 16384L; + _headers._ContentLocation = value; + } return true; } return false; @@ -6445,8 +6659,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 268435456L) == 0) { - _bits |= 268435456L; - _headers._WWWAuthenticate = value; + if (isNotNull) + { + _bits |= 268435456L; + _headers._WWWAuthenticate = value; + } return true; } return false; @@ -6459,8 +6676,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32768L) == 0) { - _bits |= 32768L; - _headers._ContentMD5 = value; + if (isNotNull) + { + _bits |= 32768L; + _headers._ContentMD5 = value; + } return true; } return false; @@ -6469,8 +6689,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16777216L) == 0) { - _bits |= 16777216L; - _headers._RetryAfter = value; + if (isNotNull) + { + _bits |= 16777216L; + _headers._RetryAfter = value; + } return true; } return false; @@ -6483,8 +6706,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4194304L) == 0) { - _bits |= 4194304L; - _headers._Location = value; + if (isNotNull) + { + _bits |= 4194304L; + _headers._Location = value; + } return true; } return false; @@ -6497,8 +6723,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8388608L) == 0) { - _bits |= 8388608L; - _headers._ProxyAuthenticate = value; + if (isNotNull) + { + _bits |= 8388608L; + _headers._ProxyAuthenticate = value; + } return true; } return false; @@ -6511,8 +6740,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 536870912L) == 0) { - _bits |= 536870912L; - _headers._AccessControlAllowCredentials = value; + if (isNotNull) + { + _bits |= 536870912L; + _headers._AccessControlAllowCredentials = value; + } return true; } return false; @@ -6525,8 +6757,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1073741824L) == 0) { - _bits |= 1073741824L; - _headers._AccessControlAllowHeaders = value; + if (isNotNull) + { + _bits |= 1073741824L; + _headers._AccessControlAllowHeaders = value; + } return true; } return false; @@ -6535,8 +6770,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2147483648L) == 0) { - _bits |= 2147483648L; - _headers._AccessControlAllowMethods = value; + if (isNotNull) + { + _bits |= 2147483648L; + _headers._AccessControlAllowMethods = value; + } return true; } return false; @@ -6549,8 +6787,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4294967296L) == 0) { - _bits |= 4294967296L; - _headers._AccessControlAllowOrigin = value; + if (isNotNull) + { + _bits |= 4294967296L; + _headers._AccessControlAllowOrigin = value; + } return true; } return false; @@ -6563,8 +6804,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8589934592L) == 0) { - _bits |= 8589934592L; - _headers._AccessControlExposeHeaders = value; + if (isNotNull) + { + _bits |= 8589934592L; + _headers._AccessControlExposeHeaders = value; + } return true; } return false; @@ -6577,8 +6821,11 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 17179869184L) == 0) { - _bits |= 17179869184L; - _headers._AccessControlMaxAge = value; + if (isNotNull) + { + _bits |= 17179869184L; + _headers._AccessControlMaxAge = value; + } return true; } return false; diff --git a/src/Kestrel.Core/Internal/Http/HttpHeaders.cs b/src/Kestrel.Core/Internal/Http/HttpHeaders.cs index 92061b5d8..cd318dfb7 100644 --- a/src/Kestrel.Core/Internal/Http/HttpHeaders.cs +++ b/src/Kestrel.Core/Internal/Http/HttpHeaders.cs @@ -45,7 +45,14 @@ StringValues IHeaderDictionary.this[string key] { ThrowHeadersReadOnlyException(); } - SetValueFast(key, value); + if (value.Count == 0) + { + RemoveFast(key); + } + else + { + SetValueFast(key, value); + } } } diff --git a/src/Kestrel.Core/Internal/Http/HttpProtocol.cs b/src/Kestrel.Core/Internal/Http/HttpProtocol.cs index 01bde8560..e58b3eebb 100644 --- a/src/Kestrel.Core/Internal/Http/HttpProtocol.cs +++ b/src/Kestrel.Core/Internal/Http/HttpProtocol.cs @@ -1110,7 +1110,6 @@ private void CreateResponseHeader(bool appCompleted) var hasConnection = responseHeaders.HasConnection; var connectionOptions = HttpHeaders.ParseConnection(responseHeaders.HeaderConnection); var hasTransferEncoding = responseHeaders.HasTransferEncoding; - var transferCoding = HttpHeaders.GetFinalTransferCoding(responseHeaders.HeaderTransferEncoding); if (_keepAlive && hasConnection && (connectionOptions & ConnectionOptions.KeepAlive) != ConnectionOptions.KeepAlive) { @@ -1122,7 +1121,8 @@ private void CreateResponseHeader(bool appCompleted) // chunked is applied to a response payload body, the sender MUST either // apply chunked as the final transfer coding or terminate the message // by closing the connection. - if (hasTransferEncoding && transferCoding != TransferCoding.Chunked) + if (hasTransferEncoding && + HttpHeaders.GetFinalTransferCoding(responseHeaders.HeaderTransferEncoding) != TransferCoding.Chunked) { _keepAlive = false; } diff --git a/src/Kestrel.Core/Internal/Http/HttpResponseHeaders.cs b/src/Kestrel.Core/Internal/Http/HttpResponseHeaders.cs index f559102c6..1df80f3dc 100644 --- a/src/Kestrel.Core/Internal/Http/HttpResponseHeaders.cs +++ b/src/Kestrel.Core/Internal/Http/HttpResponseHeaders.cs @@ -17,14 +17,6 @@ public partial class HttpResponseHeaders : HttpHeaders private static readonly byte[] _CrLf = new[] { (byte)'\r', (byte)'\n' }; private static readonly byte[] _colonSpace = new[] { (byte)':', (byte)' ' }; - public bool HasConnection => HeaderConnection.Count != 0; - - public bool HasTransferEncoding => HeaderTransferEncoding.Count != 0; - - public bool HasServer => HeaderServer.Count != 0; - - public bool HasDate => HeaderDate.Count != 0; - public Enumerator GetEnumerator() { return new Enumerator(this); diff --git a/tools/CodeGenerator/KnownHeaders.cs b/tools/CodeGenerator/KnownHeaders.cs index 6aa165468..8d2764c09 100644 --- a/tools/CodeGenerator/KnownHeaders.cs +++ b/tools/CodeGenerator/KnownHeaders.cs @@ -68,6 +68,8 @@ class KnownHeader public byte[] Bytes => Encoding.ASCII.GetBytes($"\r\n{Name}: "); public int BytesOffset { get; set; } public int BytesCount { get; set; } + public bool ExistenceCheck { get; set; } + public bool FastCount { get; set; } public bool EnhancedSetter { get; set; } public bool PrimaryHeader { get; set; } public string TestBit() => $"(_bits & {1L << Index}L) != 0"; @@ -168,6 +170,15 @@ public static string GeneratedFile() "Access-Control-Request-Method", "Access-Control-Request-Headers", }; + var requestHeadersExistence = new[] + { + "Connection", + "Transfer-Encoding", + }; + var requestHeadersCount = new[] + { + "Host" + }; var requestHeaders = commonHeaders.Concat(new[] { "Accept", @@ -197,7 +208,9 @@ public static string GeneratedFile() { Name = header, Index = index, - PrimaryHeader = requestPrimaryHeaders.Contains(header) + PrimaryHeader = requestPrimaryHeaders.Contains(header), + ExistenceCheck = requestHeadersExistence.Contains(header), + FastCount = requestHeadersCount.Contains(header) }) .Concat(new[] { new KnownHeader { @@ -209,6 +222,13 @@ public static string GeneratedFile() Debug.Assert(requestHeaders.Length <= 64); Debug.Assert(requestHeaders.Max(x => x.Index) <= 62); + var responseHeadersExistence = new[] + { + "Connection", + "Server", + "Date", + "Transfer-Encoding" + }; var enhancedHeaders = new[] { "Connection", @@ -245,6 +265,7 @@ public static string GeneratedFile() Name = header, Index = index, EnhancedSetter = enhancedHeaders.Contains(header), + ExistenceCheck = responseHeadersExistence.Contains(header), PrimaryHeader = responsePrimaryHeaders.Contains(header) }) .Concat(new[] { new KnownHeader @@ -311,6 +332,10 @@ public partial class {loop.ClassName} private long _bits = 0; private HeaderReferences _headers; +{Each(loop.Headers.Where(header => header.ExistenceCheck), header => $@" + public bool Has{header.Identifier} => {header.TestBit()};")} +{Each(loop.Headers.Where(header => header.FastCount), header => $@" + public int {header.Identifier}Count => _headers._{header.Identifier}.Count;")} {Each(loop.Headers, header => $@" public StringValues Header{header.Identifier} {{{(header.Identifier == "ContentLength" ? $@" @@ -408,6 +433,7 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) {{{(loop.ClassName == "HttpResponseHeaders" ? @" ValidateHeaderCharacters(value);" : "")} + var isNotNull = value.Count > 0; switch (key.Length) {{{Each(loop.HeadersByLength, byLength => $@" case {byLength.Key}: @@ -422,9 +448,12 @@ protected override bool AddValueFast(string key, in StringValues value) return false;" : $@" if ({header.TestNotBit()}) {{ - {header.SetBit()}; - _headers._{header.Identifier} = value;{(header.EnhancedSetter == false ? "" : $@" - _headers._raw{header.Identifier} = null;")} + if (isNotNull) + {{ + {header.SetBit()}; + _headers._{header.Identifier} = value;{(header.EnhancedSetter == false ? "" : $@" + _headers._raw{header.Identifier} = null;")} + }} return true; }} return false;")} From 776cc997aead4ba35027b0fd33789b8d0ee26b5d Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 14 Mar 2018 02:31:21 -0400 Subject: [PATCH 2/6] EnsureHostHeaderExists perf --- .../Internal/Http/Http1Connection.cs | 39 +++++--- .../Internal/Http2/Http2Stream.cs | 5 +- .../Internal/Infrastructure/HttpUtilities.cs | 94 +++++++++++-------- test/Kestrel.Core.Tests/HttpUtilitiesTest.cs | 5 +- 4 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/Kestrel.Core/Internal/Http/Http1Connection.cs b/src/Kestrel.Core/Internal/Http/Http1Connection.cs index d0105f9bf..b1c45a0da 100644 --- a/src/Kestrel.Core/Internal/Http/Http1Connection.cs +++ b/src/Kestrel.Core/Internal/Http/Http1Connection.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Globalization; using System.IO.Pipelines; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -361,8 +362,9 @@ internal void EnsureHostHeaderExists() // Host header field with an invalid field-value. var host = HttpRequestHeaders.HeaderHost; + var hostCount = host.Count; var hostText = host.ToString(); - if (host.Count <= 0) + if (hostCount <= 0) { if (_httpVersion == Http.HttpVersion.Http10) { @@ -370,13 +372,28 @@ internal void EnsureHostHeaderExists() } BadHttpRequestException.Throw(RequestRejectionReason.MissingHostHeader); } - else if (host.Count > 1) + else if (hostCount > 1) { BadHttpRequestException.Throw(RequestRejectionReason.MultipleHostHeaders); } - else if (_requestTargetForm == HttpRequestTarget.AuthorityForm) + else if (_requestTargetForm != HttpRequestTarget.OriginForm) { - if (!host.Equals(RawTarget)) + // Tail call + ValidateNonOrginHostHeader(hostText); + } + else + { + // Tail call + HttpUtilities.ValidateHostHeader(hostText); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private void ValidateNonOrginHostHeader(string hostText) + { + if (_requestTargetForm == HttpRequestTarget.AuthorityForm) + { + if (hostText != RawTarget) { BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } @@ -390,20 +407,18 @@ internal void EnsureHostHeaderExists() // System.Uri doesn't not tell us if the port was in the original string or not. // When IsDefaultPort = true, we will allow Host: with or without the default port - if (host != _absoluteRequestTarget.Authority) + if (hostText != _absoluteRequestTarget.Authority) { if (!_absoluteRequestTarget.IsDefaultPort - || host != _absoluteRequestTarget.Authority + ":" + _absoluteRequestTarget.Port.ToString(CultureInfo.InvariantCulture)) + || hostText != _absoluteRequestTarget.Authority + ":" + _absoluteRequestTarget.Port.ToString(CultureInfo.InvariantCulture)) { BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } } - if (!HttpUtilities.IsValidHostHeader(hostText)) - { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); - } + // Tail call + HttpUtilities.ValidateHostHeader(hostText); } protected override void OnReset() @@ -454,10 +469,8 @@ protected override bool TryParseRequest(ReadResult result, out bool endConnectio { if (_requestProcessingStatus == RequestProcessingStatus.ParsingHeaders) { - BadHttpRequestException.Throw(RequestRejectionReason - .MalformedRequestInvalidHeaders); + BadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); } - throw; } finally { diff --git a/src/Kestrel.Core/Internal/Http2/Http2Stream.cs b/src/Kestrel.Core/Internal/Http2/Http2Stream.cs index fd73b5ac9..b1f754884 100644 --- a/src/Kestrel.Core/Internal/Http2/Http2Stream.cs +++ b/src/Kestrel.Core/Internal/Http2/Http2Stream.cs @@ -110,10 +110,7 @@ protected override bool TryParseRequest(ReadResult result, out bool endConnectio } var hostText = host.ToString(); - if (!HttpUtilities.IsValidHostHeader(hostText)) - { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); - } + HttpUtilities.ValidateHostHeader(hostText); endConnection = false; return true; diff --git a/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs b/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs index bfc3baa89..96d575525 100644 --- a/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs +++ b/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs @@ -426,45 +426,51 @@ public static string SchemeToString(HttpScheme scheme) } } - public static bool IsValidHostHeader(string hostText) + public static void ValidateHostHeader(string hostText) { // The spec allows empty values if (string.IsNullOrEmpty(hostText)) { - return true; + return; } - if (hostText[0] == '[') + var firstChar = hostText[0]; + if (firstChar == '[') { - return IsValidIPv6Host(hostText); + // Tail call + ValidateIPv6Host(hostText); } - - if (hostText[0] == ':') + else { - // Only a port - return false; - } + if (firstChar == ':') + { + // Only a port + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + } - var i = 0; - for (; i < hostText.Length; i++) - { - if (!IsValidHostChar(hostText[i])) + // Enregister array + var hostCharValidity = HostCharValidity; + var i = 0; + for (; i < hostText.Length; i++) { - break; + var ch = hostText[i]; + // Bounds check and elimiate second bounds check + if ((uint)ch > (uint)hostCharValidity.Length || !hostCharValidity[ch]) + { + break; + } } - } - return IsValidHostPort(hostText, i); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsValidHostChar(char ch) - { - return ch < HostCharValidity.Length && HostCharValidity[ch]; + if (i < hostText.Length) + { + // Tail call + ValidateHostPort(hostText, i); + } + } } // The lead '[' was already checked - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsValidIPv6Host(string hostText) + private static void ValidateIPv6Host(string hostText) { for (var i = 1; i < hostText.Length; i++) { @@ -474,58 +480,72 @@ private static bool IsValidIPv6Host(string hostText) // [::1] is the shortest valid IPv6 host if (i < 4) { - return false; + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + } + else + { + // Tail call + ValidateHostPort(hostText, i + 1); + return; } - return IsValidHostPort(hostText, i + 1); } if (!IsHex(ch) && ch != ':' && ch != '.') { - return false; + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } // Must contain a ']' - return false; + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsValidHostPort(string hostText, int offset) + private static void ValidateHostPort(string hostText, int offset) { if (offset == hostText.Length) { - return true; + return; } if (hostText[offset] != ':' || hostText.Length == offset + 1) { // Must have at least one number after the colon if present. - return false; + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } for (var i = offset + 1; i < hostText.Length; i++) { if (!IsNumeric(hostText[i])) { - return false; + BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } - - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsNumeric(char ch) { - return '0' <= ch && ch <= '9'; + // '0' <= ch && ch <= '9' + // (uint)(ch - '0') <= (uint)('9' - '0') + + // Subtract start of range '0' + // Cast to uint to change negative numbers to large numbers + // Check if less than 10 representing chars '0' - '9' + return (uint)(ch - '0') < 10u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsHex(char ch) { return IsNumeric(ch) - || ('a' <= ch && ch <= 'f') - || ('A' <= ch && ch <= 'F'); + // || ('a' <= ch && ch <= 'f') + // || ('A' <= ch && ch <= 'F'); + + // Lowercase indiscriminately (or with 32) + // Subtract start of range 'a' + // Cast to uint to change negative numbers to large numbers + // Check if less than 6 representing chars 'a' - 'f' + || (uint)((ch | 32) - 'a') < 6u; } } } diff --git a/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs b/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs index d2c1233ce..cb08758e7 100644 --- a/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs +++ b/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs @@ -170,7 +170,8 @@ public static TheoryData HostHeaderData [MemberData(nameof(HostHeaderData))] public void ValidHostHeadersParsed(string host) { - Assert.True(HttpUtilities.IsValidHostHeader(host)); + HttpUtilities.ValidateHostHeader(host); + Assert.True(true); } public static TheoryData HostHeaderInvalidData @@ -224,7 +225,7 @@ public static TheoryData HostHeaderInvalidData [MemberData(nameof(HostHeaderInvalidData))] public void InvalidHostHeadersRejected(string host) { - Assert.False(HttpUtilities.IsValidHostHeader(host)); + Assert.Throws(() => HttpUtilities.ValidateHostHeader(host)); } } } \ No newline at end of file From 8e1a024910cd51958c85fe7bd94a97a4326db32f Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Thu, 15 Mar 2018 10:45:07 -0400 Subject: [PATCH 3/6] Skip some bounds checks --- .../Internal/Infrastructure/HttpUtilities.cs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs b/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs index 96d575525..3626835ee 100644 --- a/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs +++ b/src/Kestrel.Core/Internal/Infrastructure/HttpUtilities.cs @@ -428,9 +428,11 @@ public static string SchemeToString(HttpScheme scheme) public static void ValidateHostHeader(string hostText) { - // The spec allows empty values - if (string.IsNullOrEmpty(hostText)) + // This is a string.IsNullOrEmpty test, but arranged to elmininate the + // bounds check from accessing the firstChar of the string + if (hostText is null || 0u >= (uint)hostText.Length) { + // The spec allows empty values return; } @@ -453,9 +455,9 @@ public static void ValidateHostHeader(string hostText) var i = 0; for (; i < hostText.Length; i++) { - var ch = hostText[i]; + var ch = (int)hostText[i]; // Bounds check and elimiate second bounds check - if ((uint)ch > (uint)hostCharValidity.Length || !hostCharValidity[ch]) + if ((uint)ch >= (uint)hostCharValidity.Length || !hostCharValidity[ch]) { break; } @@ -502,24 +504,38 @@ private static void ValidateIPv6Host(string hostText) private static void ValidateHostPort(string hostText, int offset) { - if (offset == hostText.Length) + // Skip bounds check for accessing the [offset] element + if ((uint)offset >= (uint)hostText.Length) { return; } - if (hostText[offset] != ':' || hostText.Length == offset + 1) + var firstChar = hostText[offset]; + offset++; + if (firstChar != ':' || (uint)offset >= (uint)hostText.Length) { // Must have at least one number after the colon if present. BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } - for (var i = offset + 1; i < hostText.Length; i++) + // This do+if check rather than for loop is to elimitate the bounds check, since + // the Jit doesn't currently pick up on it when starting at a variable offset + do { - if (!IsNumeric(hostText[i])) + // Elminate bounds check for array access + if ((uint)offset >= (uint)hostText.Length) + { + // Length reached, end of loop + break; + } + + var ch = hostText[offset]; + offset++; + if (!IsNumeric(ch)) { BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } - } + } while (true); } [MethodImpl(MethodImplOptions.AggressiveInlining)] From d9f74b3003996aa2ccd7377b75766c7ed0b9ce52 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 16 Mar 2018 10:08:14 -0400 Subject: [PATCH 4/6] Skip StringValue copy --- src/Kestrel.Core/Internal/Http/Http1Connection.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Kestrel.Core/Internal/Http/Http1Connection.cs b/src/Kestrel.Core/Internal/Http/Http1Connection.cs index b1c45a0da..af32e863f 100644 --- a/src/Kestrel.Core/Internal/Http/Http1Connection.cs +++ b/src/Kestrel.Core/Internal/Http/Http1Connection.cs @@ -361,9 +361,8 @@ internal void EnsureHostHeaderExists() // request message that contains more than one Host header field or a // Host header field with an invalid field-value. - var host = HttpRequestHeaders.HeaderHost; - var hostCount = host.Count; - var hostText = host.ToString(); + var hostCount = HttpRequestHeaders.HostCount; + var hostText = HttpRequestHeaders.HeaderHost.ToString(); if (hostCount <= 0) { if (_httpVersion == Http.HttpVersion.Http10) From 301c8f95162fff4a1f9420faa286e263f72d2edf Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 16 Mar 2018 10:03:19 -0400 Subject: [PATCH 5/6] feedback --- src/Kestrel.Core/Internal/Http/Http1Connection.cs | 1 + test/Kestrel.Core.Tests/HttpUtilitiesTest.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Kestrel.Core/Internal/Http/Http1Connection.cs b/src/Kestrel.Core/Internal/Http/Http1Connection.cs index af32e863f..733569c51 100644 --- a/src/Kestrel.Core/Internal/Http/Http1Connection.cs +++ b/src/Kestrel.Core/Internal/Http/Http1Connection.cs @@ -470,6 +470,7 @@ protected override bool TryParseRequest(ReadResult result, out bool endConnectio { BadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); } + throw; } finally { diff --git a/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs b/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs index cb08758e7..b503eab04 100644 --- a/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs +++ b/test/Kestrel.Core.Tests/HttpUtilitiesTest.cs @@ -171,7 +171,7 @@ public static TheoryData HostHeaderData public void ValidHostHeadersParsed(string host) { HttpUtilities.ValidateHostHeader(host); - Assert.True(true); + // Shouldn't throw } public static TheoryData HostHeaderInvalidData From b932a4fc010b0c3fbed00771a650b920f2de2825 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 16 Mar 2018 21:40:48 -0400 Subject: [PATCH 6/6] Hoist IsNull check --- .../Internal/Http/HttpHeaders.Generated.cs | 556 +++++------------- src/Kestrel.Core/Internal/Http/HttpHeaders.cs | 2 +- tools/CodeGenerator/KnownHeaders.cs | 10 +- 3 files changed, 164 insertions(+), 404 deletions(-) diff --git a/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs b/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs index 5704b85ae..d84f15706 100644 --- a/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs +++ b/src/Kestrel.Core/Internal/Http/HttpHeaders.Generated.cs @@ -1607,7 +1607,6 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) { - var isNotNull = value.Count > 0; switch (key.Length) { case 13: @@ -1616,11 +1615,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1L) == 0) { - if (isNotNull) - { - _bits |= 1L; - _headers._CacheControl = value; - } + _bits |= 1L; + _headers._CacheControl = value; return true; } return false; @@ -1629,11 +1625,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 65536L) == 0) { - if (isNotNull) - { - _bits |= 65536L; - _headers._ContentRange = value; - } + _bits |= 65536L; + _headers._ContentRange = value; return true; } return false; @@ -1642,11 +1635,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 262144L) == 0) { - if (isNotNull) - { - _bits |= 262144L; - _headers._LastModified = value; - } + _bits |= 262144L; + _headers._LastModified = value; return true; } return false; @@ -1655,11 +1645,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8388608L) == 0) { - if (isNotNull) - { - _bits |= 8388608L; - _headers._Authorization = value; - } + _bits |= 8388608L; + _headers._Authorization = value; return true; } return false; @@ -1668,11 +1655,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1073741824L) == 0) { - if (isNotNull) - { - _bits |= 1073741824L; - _headers._IfNoneMatch = value; - } + _bits |= 1073741824L; + _headers._IfNoneMatch = value; return true; } return false; @@ -1685,11 +1669,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2L) == 0) { - if (isNotNull) - { - _bits |= 2L; - _headers._Connection = value; - } + _bits |= 2L; + _headers._Connection = value; return true; } return false; @@ -1698,11 +1679,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8L) == 0) { - if (isNotNull) - { - _bits |= 8L; - _headers._KeepAlive = value; - } + _bits |= 8L; + _headers._KeepAlive = value; return true; } return false; @@ -1711,11 +1689,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 549755813888L) == 0) { - if (isNotNull) - { - _bits |= 549755813888L; - _headers._UserAgent = value; - } + _bits |= 549755813888L; + _headers._UserAgent = value; return true; } return false; @@ -1728,11 +1703,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4L) == 0) { - if (isNotNull) - { - _bits |= 4L; - _headers._Date = value; - } + _bits |= 4L; + _headers._Date = value; return true; } return false; @@ -1741,11 +1713,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 67108864L) == 0) { - if (isNotNull) - { - _bits |= 67108864L; - _headers._From = value; - } + _bits |= 67108864L; + _headers._From = value; return true; } return false; @@ -1754,11 +1723,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 134217728L) == 0) { - if (isNotNull) - { - _bits |= 134217728L; - _headers._Host = value; - } + _bits |= 134217728L; + _headers._Host = value; return true; } return false; @@ -1771,11 +1737,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16L) == 0) { - if (isNotNull) - { - _bits |= 16L; - _headers._Pragma = value; - } + _bits |= 16L; + _headers._Pragma = value; return true; } return false; @@ -1784,11 +1747,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 524288L) == 0) { - if (isNotNull) - { - _bits |= 524288L; - _headers._Accept = value; - } + _bits |= 524288L; + _headers._Accept = value; return true; } return false; @@ -1797,11 +1757,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16777216L) == 0) { - if (isNotNull) - { - _bits |= 16777216L; - _headers._Cookie = value; - } + _bits |= 16777216L; + _headers._Cookie = value; return true; } return false; @@ -1810,11 +1767,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 33554432L) == 0) { - if (isNotNull) - { - _bits |= 33554432L; - _headers._Expect = value; - } + _bits |= 33554432L; + _headers._Expect = value; return true; } return false; @@ -1823,11 +1777,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1099511627776L) == 0) { - if (isNotNull) - { - _bits |= 1099511627776L; - _headers._Origin = value; - } + _bits |= 1099511627776L; + _headers._Origin = value; return true; } return false; @@ -1840,11 +1791,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32L) == 0) { - if (isNotNull) - { - _bits |= 32L; - _headers._Trailer = value; - } + _bits |= 32L; + _headers._Trailer = value; return true; } return false; @@ -1853,11 +1801,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 128L) == 0) { - if (isNotNull) - { - _bits |= 128L; - _headers._Upgrade = value; - } + _bits |= 128L; + _headers._Upgrade = value; return true; } return false; @@ -1866,11 +1811,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 512L) == 0) { - if (isNotNull) - { - _bits |= 512L; - _headers._Warning = value; - } + _bits |= 512L; + _headers._Warning = value; return true; } return false; @@ -1879,11 +1821,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 131072L) == 0) { - if (isNotNull) - { - _bits |= 131072L; - _headers._Expires = value; - } + _bits |= 131072L; + _headers._Expires = value; return true; } return false; @@ -1892,11 +1831,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 34359738368L) == 0) { - if (isNotNull) - { - _bits |= 34359738368L; - _headers._Referer = value; - } + _bits |= 34359738368L; + _headers._Referer = value; return true; } return false; @@ -1909,11 +1845,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 64L) == 0) { - if (isNotNull) - { - _bits |= 64L; - _headers._TransferEncoding = value; - } + _bits |= 64L; + _headers._TransferEncoding = value; return true; } return false; @@ -1922,11 +1855,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 536870912L) == 0) { - if (isNotNull) - { - _bits |= 536870912L; - _headers._IfModifiedSince = value; - } + _bits |= 536870912L; + _headers._IfModifiedSince = value; return true; } return false; @@ -1939,11 +1869,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 256L) == 0) { - if (isNotNull) - { - _bits |= 256L; - _headers._Via = value; - } + _bits |= 256L; + _headers._Via = value; return true; } return false; @@ -1956,11 +1883,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1024L) == 0) { - if (isNotNull) - { - _bits |= 1024L; - _headers._Allow = value; - } + _bits |= 1024L; + _headers._Allow = value; return true; } return false; @@ -1969,11 +1893,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 68719476736L) == 0) { - if (isNotNull) - { - _bits |= 68719476736L; - _headers._Range = value; - } + _bits |= 68719476736L; + _headers._Range = value; return true; } return false; @@ -1986,11 +1907,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2048L) == 0) { - if (isNotNull) - { - _bits |= 2048L; - _headers._ContentType = value; - } + _bits |= 2048L; + _headers._ContentType = value; return true; } return false; @@ -1999,11 +1917,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8589934592L) == 0) { - if (isNotNull) - { - _bits |= 8589934592L; - _headers._MaxForwards = value; - } + _bits |= 8589934592L; + _headers._MaxForwards = value; return true; } return false; @@ -2016,11 +1931,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4096L) == 0) { - if (isNotNull) - { - _bits |= 4096L; - _headers._ContentEncoding = value; - } + _bits |= 4096L; + _headers._ContentEncoding = value; return true; } return false; @@ -2029,11 +1941,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8192L) == 0) { - if (isNotNull) - { - _bits |= 8192L; - _headers._ContentLanguage = value; - } + _bits |= 8192L; + _headers._ContentLanguage = value; return true; } return false; @@ -2042,11 +1951,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16384L) == 0) { - if (isNotNull) - { - _bits |= 16384L; - _headers._ContentLocation = value; - } + _bits |= 16384L; + _headers._ContentLocation = value; return true; } return false; @@ -2059,11 +1965,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32768L) == 0) { - if (isNotNull) - { - _bits |= 32768L; - _headers._ContentMD5 = value; - } + _bits |= 32768L; + _headers._ContentMD5 = value; return true; } return false; @@ -2076,11 +1979,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1048576L) == 0) { - if (isNotNull) - { - _bits |= 1048576L; - _headers._AcceptCharset = value; - } + _bits |= 1048576L; + _headers._AcceptCharset = value; return true; } return false; @@ -2102,11 +2002,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2097152L) == 0) { - if (isNotNull) - { - _bits |= 2097152L; - _headers._AcceptEncoding = value; - } + _bits |= 2097152L; + _headers._AcceptEncoding = value; return true; } return false; @@ -2115,11 +2012,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4194304L) == 0) { - if (isNotNull) - { - _bits |= 4194304L; - _headers._AcceptLanguage = value; - } + _bits |= 4194304L; + _headers._AcceptLanguage = value; return true; } return false; @@ -2132,11 +2026,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 268435456L) == 0) { - if (isNotNull) - { - _bits |= 268435456L; - _headers._IfMatch = value; - } + _bits |= 268435456L; + _headers._IfMatch = value; return true; } return false; @@ -2145,11 +2036,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2147483648L) == 0) { - if (isNotNull) - { - _bits |= 2147483648L; - _headers._IfRange = value; - } + _bits |= 2147483648L; + _headers._IfRange = value; return true; } return false; @@ -2162,11 +2050,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4294967296L) == 0) { - if (isNotNull) - { - _bits |= 4294967296L; - _headers._IfUnmodifiedSince = value; - } + _bits |= 4294967296L; + _headers._IfUnmodifiedSince = value; return true; } return false; @@ -2175,11 +2060,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 17179869184L) == 0) { - if (isNotNull) - { - _bits |= 17179869184L; - _headers._ProxyAuthorization = value; - } + _bits |= 17179869184L; + _headers._ProxyAuthorization = value; return true; } return false; @@ -2192,11 +2074,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 137438953472L) == 0) { - if (isNotNull) - { - _bits |= 137438953472L; - _headers._TE = value; - } + _bits |= 137438953472L; + _headers._TE = value; return true; } return false; @@ -2209,11 +2088,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 274877906944L) == 0) { - if (isNotNull) - { - _bits |= 274877906944L; - _headers._Translate = value; - } + _bits |= 274877906944L; + _headers._Translate = value; return true; } return false; @@ -2226,11 +2102,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2199023255552L) == 0) { - if (isNotNull) - { - _bits |= 2199023255552L; - _headers._AccessControlRequestMethod = value; - } + _bits |= 2199023255552L; + _headers._AccessControlRequestMethod = value; return true; } return false; @@ -2243,11 +2116,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4398046511104L) == 0) { - if (isNotNull) - { - _bits |= 4398046511104L; - _headers._AccessControlRequestHeaders = value; - } + _bits |= 4398046511104L; + _headers._AccessControlRequestHeaders = value; return true; } return false; @@ -6298,7 +6168,6 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) { ValidateHeaderCharacters(value); - var isNotNull = value.Count > 0; switch (key.Length) { case 13: @@ -6307,11 +6176,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1L) == 0) { - if (isNotNull) - { - _bits |= 1L; - _headers._CacheControl = value; - } + _bits |= 1L; + _headers._CacheControl = value; return true; } return false; @@ -6320,11 +6186,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 65536L) == 0) { - if (isNotNull) - { - _bits |= 65536L; - _headers._ContentRange = value; - } + _bits |= 65536L; + _headers._ContentRange = value; return true; } return false; @@ -6333,11 +6196,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 262144L) == 0) { - if (isNotNull) - { - _bits |= 262144L; - _headers._LastModified = value; - } + _bits |= 262144L; + _headers._LastModified = value; return true; } return false; @@ -6346,11 +6206,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 524288L) == 0) { - if (isNotNull) - { - _bits |= 524288L; - _headers._AcceptRanges = value; - } + _bits |= 524288L; + _headers._AcceptRanges = value; return true; } return false; @@ -6363,12 +6220,9 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2L) == 0) { - if (isNotNull) - { - _bits |= 2L; - _headers._Connection = value; - _headers._rawConnection = null; - } + _bits |= 2L; + _headers._Connection = value; + _headers._rawConnection = null; return true; } return false; @@ -6377,11 +6231,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8L) == 0) { - if (isNotNull) - { - _bits |= 8L; - _headers._KeepAlive = value; - } + _bits |= 8L; + _headers._KeepAlive = value; return true; } return false; @@ -6390,11 +6241,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 67108864L) == 0) { - if (isNotNull) - { - _bits |= 67108864L; - _headers._SetCookie = value; - } + _bits |= 67108864L; + _headers._SetCookie = value; return true; } return false; @@ -6407,12 +6255,9 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4L) == 0) { - if (isNotNull) - { - _bits |= 4L; - _headers._Date = value; - _headers._rawDate = null; - } + _bits |= 4L; + _headers._Date = value; + _headers._rawDate = null; return true; } return false; @@ -6421,11 +6266,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2097152L) == 0) { - if (isNotNull) - { - _bits |= 2097152L; - _headers._ETag = value; - } + _bits |= 2097152L; + _headers._ETag = value; return true; } return false; @@ -6434,11 +6276,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 134217728L) == 0) { - if (isNotNull) - { - _bits |= 134217728L; - _headers._Vary = value; - } + _bits |= 134217728L; + _headers._Vary = value; return true; } return false; @@ -6451,11 +6290,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16L) == 0) { - if (isNotNull) - { - _bits |= 16L; - _headers._Pragma = value; - } + _bits |= 16L; + _headers._Pragma = value; return true; } return false; @@ -6464,12 +6300,9 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 33554432L) == 0) { - if (isNotNull) - { - _bits |= 33554432L; - _headers._Server = value; - _headers._rawServer = null; - } + _bits |= 33554432L; + _headers._Server = value; + _headers._rawServer = null; return true; } return false; @@ -6482,11 +6315,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32L) == 0) { - if (isNotNull) - { - _bits |= 32L; - _headers._Trailer = value; - } + _bits |= 32L; + _headers._Trailer = value; return true; } return false; @@ -6495,11 +6325,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 128L) == 0) { - if (isNotNull) - { - _bits |= 128L; - _headers._Upgrade = value; - } + _bits |= 128L; + _headers._Upgrade = value; return true; } return false; @@ -6508,11 +6335,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 512L) == 0) { - if (isNotNull) - { - _bits |= 512L; - _headers._Warning = value; - } + _bits |= 512L; + _headers._Warning = value; return true; } return false; @@ -6521,11 +6345,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 131072L) == 0) { - if (isNotNull) - { - _bits |= 131072L; - _headers._Expires = value; - } + _bits |= 131072L; + _headers._Expires = value; return true; } return false; @@ -6538,12 +6359,9 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 64L) == 0) { - if (isNotNull) - { - _bits |= 64L; - _headers._TransferEncoding = value; - _headers._rawTransferEncoding = null; - } + _bits |= 64L; + _headers._TransferEncoding = value; + _headers._rawTransferEncoding = null; return true; } return false; @@ -6556,11 +6374,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 256L) == 0) { - if (isNotNull) - { - _bits |= 256L; - _headers._Via = value; - } + _bits |= 256L; + _headers._Via = value; return true; } return false; @@ -6569,11 +6384,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1048576L) == 0) { - if (isNotNull) - { - _bits |= 1048576L; - _headers._Age = value; - } + _bits |= 1048576L; + _headers._Age = value; return true; } return false; @@ -6586,11 +6398,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1024L) == 0) { - if (isNotNull) - { - _bits |= 1024L; - _headers._Allow = value; - } + _bits |= 1024L; + _headers._Allow = value; return true; } return false; @@ -6603,11 +6412,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2048L) == 0) { - if (isNotNull) - { - _bits |= 2048L; - _headers._ContentType = value; - } + _bits |= 2048L; + _headers._ContentType = value; return true; } return false; @@ -6620,11 +6426,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4096L) == 0) { - if (isNotNull) - { - _bits |= 4096L; - _headers._ContentEncoding = value; - } + _bits |= 4096L; + _headers._ContentEncoding = value; return true; } return false; @@ -6633,11 +6436,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8192L) == 0) { - if (isNotNull) - { - _bits |= 8192L; - _headers._ContentLanguage = value; - } + _bits |= 8192L; + _headers._ContentLanguage = value; return true; } return false; @@ -6646,11 +6446,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16384L) == 0) { - if (isNotNull) - { - _bits |= 16384L; - _headers._ContentLocation = value; - } + _bits |= 16384L; + _headers._ContentLocation = value; return true; } return false; @@ -6659,11 +6456,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 268435456L) == 0) { - if (isNotNull) - { - _bits |= 268435456L; - _headers._WWWAuthenticate = value; - } + _bits |= 268435456L; + _headers._WWWAuthenticate = value; return true; } return false; @@ -6676,11 +6470,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 32768L) == 0) { - if (isNotNull) - { - _bits |= 32768L; - _headers._ContentMD5 = value; - } + _bits |= 32768L; + _headers._ContentMD5 = value; return true; } return false; @@ -6689,11 +6480,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 16777216L) == 0) { - if (isNotNull) - { - _bits |= 16777216L; - _headers._RetryAfter = value; - } + _bits |= 16777216L; + _headers._RetryAfter = value; return true; } return false; @@ -6706,11 +6494,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4194304L) == 0) { - if (isNotNull) - { - _bits |= 4194304L; - _headers._Location = value; - } + _bits |= 4194304L; + _headers._Location = value; return true; } return false; @@ -6723,11 +6508,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8388608L) == 0) { - if (isNotNull) - { - _bits |= 8388608L; - _headers._ProxyAuthenticate = value; - } + _bits |= 8388608L; + _headers._ProxyAuthenticate = value; return true; } return false; @@ -6740,11 +6522,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 536870912L) == 0) { - if (isNotNull) - { - _bits |= 536870912L; - _headers._AccessControlAllowCredentials = value; - } + _bits |= 536870912L; + _headers._AccessControlAllowCredentials = value; return true; } return false; @@ -6757,11 +6536,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 1073741824L) == 0) { - if (isNotNull) - { - _bits |= 1073741824L; - _headers._AccessControlAllowHeaders = value; - } + _bits |= 1073741824L; + _headers._AccessControlAllowHeaders = value; return true; } return false; @@ -6770,11 +6546,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 2147483648L) == 0) { - if (isNotNull) - { - _bits |= 2147483648L; - _headers._AccessControlAllowMethods = value; - } + _bits |= 2147483648L; + _headers._AccessControlAllowMethods = value; return true; } return false; @@ -6787,11 +6560,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 4294967296L) == 0) { - if (isNotNull) - { - _bits |= 4294967296L; - _headers._AccessControlAllowOrigin = value; - } + _bits |= 4294967296L; + _headers._AccessControlAllowOrigin = value; return true; } return false; @@ -6804,11 +6574,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 8589934592L) == 0) { - if (isNotNull) - { - _bits |= 8589934592L; - _headers._AccessControlExposeHeaders = value; - } + _bits |= 8589934592L; + _headers._AccessControlExposeHeaders = value; return true; } return false; @@ -6821,11 +6588,8 @@ protected override bool AddValueFast(string key, in StringValues value) { if ((_bits & 17179869184L) == 0) { - if (isNotNull) - { - _bits |= 17179869184L; - _headers._AccessControlMaxAge = value; - } + _bits |= 17179869184L; + _headers._AccessControlMaxAge = value; return true; } return false; diff --git a/src/Kestrel.Core/Internal/Http/HttpHeaders.cs b/src/Kestrel.Core/Internal/Http/HttpHeaders.cs index cd318dfb7..444ac6277 100644 --- a/src/Kestrel.Core/Internal/Http/HttpHeaders.cs +++ b/src/Kestrel.Core/Internal/Http/HttpHeaders.cs @@ -171,7 +171,7 @@ void IDictionary.Add(string key, StringValues value) ThrowHeadersReadOnlyException(); } - if (!AddValueFast(key, value)) + if (value.Count > 0 && !AddValueFast(key, value)) { ThrowDuplicateKeyException(); } diff --git a/tools/CodeGenerator/KnownHeaders.cs b/tools/CodeGenerator/KnownHeaders.cs index 8d2764c09..08646dc61 100644 --- a/tools/CodeGenerator/KnownHeaders.cs +++ b/tools/CodeGenerator/KnownHeaders.cs @@ -433,7 +433,6 @@ protected override void SetValueFast(string key, in StringValues value) protected override bool AddValueFast(string key, in StringValues value) {{{(loop.ClassName == "HttpResponseHeaders" ? @" ValidateHeaderCharacters(value);" : "")} - var isNotNull = value.Count > 0; switch (key.Length) {{{Each(loop.HeadersByLength, byLength => $@" case {byLength.Key}: @@ -448,12 +447,9 @@ protected override bool AddValueFast(string key, in StringValues value) return false;" : $@" if ({header.TestNotBit()}) {{ - if (isNotNull) - {{ - {header.SetBit()}; - _headers._{header.Identifier} = value;{(header.EnhancedSetter == false ? "" : $@" - _headers._raw{header.Identifier} = null;")} - }} + {header.SetBit()}; + _headers._{header.Identifier} = value;{(header.EnhancedSetter == false ? "" : $@" + _headers._raw{header.Identifier} = null;")} return true; }} return false;")}