From 1150b211cc8dbb0e48de92262256526ef7e7c22a Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 15 Aug 2020 12:21:25 +1200 Subject: [PATCH] HTTP2: Fix known header type not reset for multi-value headers (#24918) --- .../Internal/Http2/Http2HeaderEnumerator.cs | 4 +- .../Core/test/Http2HeadersEnumeratorTests.cs | 51 ++++++++++++------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2HeaderEnumerator.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2HeaderEnumerator.cs index 6e890dcaf7..84f2461e96 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2HeaderEnumerator.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2HeaderEnumerator.cs @@ -90,10 +90,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 private bool SetCurrent(string name, StringValues value, KnownHeaderType knownHeaderType) { + _knownHeaderType = knownHeaderType; + if (value.Count == 1) { Current = new KeyValuePair(name, value.ToString()); - _knownHeaderType = knownHeaderType; _hasMultipleValues = false; return true; } @@ -101,7 +102,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 { _stringValuesEnumerator = value.GetEnumerator(); _hasMultipleValues = true; - return MoveNextOnStringEnumerator(name); } } diff --git a/src/Servers/Kestrel/Core/test/Http2HeadersEnumeratorTests.cs b/src/Servers/Kestrel/Core/test/Http2HeadersEnumeratorTests.cs index fa6e94095a..dfaea9fa0f 100644 --- a/src/Servers/Kestrel/Core/test/Http2HeadersEnumeratorTests.cs +++ b/src/Servers/Kestrel/Core/test/Http2HeadersEnumeratorTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Net.Http.HPack; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2; @@ -21,7 +22,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests ContentLength = 9, HeaderAcceptRanges = "AcceptRanges!", HeaderAge = new StringValues(new[] { "1", "2" }), - HeaderDate = "Date!" + HeaderDate = "Date!", + HeaderGrpcEncoding = "Identity!" }; responseHeaders.Append("Name1", "Value1"); responseHeaders.Append("Name2", "Value2-1"); @@ -35,15 +37,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.Equal(new[] { - new KeyValuePair("Date", "Date!"), - new KeyValuePair("Accept-Ranges", "AcceptRanges!"), - new KeyValuePair("Age", "1"), - new KeyValuePair("Age", "2"), - new KeyValuePair("Content-Length", "9"), - new KeyValuePair("Name1", "Value1"), - new KeyValuePair("Name2", "Value2-1"), - new KeyValuePair("Name2", "Value2-2"), - new KeyValuePair("Name3", "Value3"), + CreateHeaderResult(H2StaticTable.Date, "Date", "Date!"), + CreateHeaderResult(-1, "Grpc-Encoding", "Identity!"), + CreateHeaderResult(H2StaticTable.AcceptRanges, "Accept-Ranges", "AcceptRanges!"), + CreateHeaderResult(H2StaticTable.Age, "Age", "1"), + CreateHeaderResult(H2StaticTable.Age, "Age", "2"), + CreateHeaderResult(H2StaticTable.ContentLength, "Content-Length", "9"), + CreateHeaderResult(-1, "Name1", "Value1"), + CreateHeaderResult(-1, "Name2", "Value2-1"), + CreateHeaderResult(-1, "Name2", "Value2-2"), + CreateHeaderResult(-1, "Name3", "Value3"), }, headers); } @@ -67,11 +70,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.Equal(new[] { - new KeyValuePair("ETag", "ETag!"), - new KeyValuePair("Name1", "Value1"), - new KeyValuePair("Name2", "Value2-1"), - new KeyValuePair("Name2", "Value2-2"), - new KeyValuePair("Name3", "Value3"), + CreateHeaderResult(H2StaticTable.ETag, "ETag", "ETag!"), + CreateHeaderResult(-1, "Name1", "Value1"), + CreateHeaderResult(-1, "Name2", "Value2-1"), + CreateHeaderResult(-1, "Name2", "Value2-2"), + CreateHeaderResult(-1, "Name3", "Value3"), }, headers); } @@ -89,14 +92,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.True(e.MoveNext()); Assert.Equal("Name1", e.Current.Key); Assert.Equal("Value1", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.True(e.MoveNext()); Assert.Equal("Name2", e.Current.Key); Assert.Equal("Value2-1", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.True(e.MoveNext()); Assert.Equal("Name2", e.Current.Key); Assert.Equal("Value2-2", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); var responseTrailers = new HttpResponseTrailers { @@ -111,30 +117,39 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests Assert.True(e.MoveNext()); Assert.Equal("Grpc-Status", e.Current.Key); Assert.Equal("1", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.True(e.MoveNext()); Assert.Equal("Name1", e.Current.Key); Assert.Equal("Value1", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.True(e.MoveNext()); Assert.Equal("Name2", e.Current.Key); Assert.Equal("Value2-1", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.True(e.MoveNext()); Assert.Equal("Name2", e.Current.Key); Assert.Equal("Value2-2", e.Current.Value); + Assert.Equal(-1, e.HPackStaticTableId); Assert.False(e.MoveNext()); } - private KeyValuePair[] GetNormalizedHeaders(Http2HeadersEnumerator enumerator) + private (int HPackStaticTableId, string Name, string Value)[] GetNormalizedHeaders(Http2HeadersEnumerator enumerator) { - var headers = new List>(); + var headers = new List<(int HPackStaticTableId, string Name, string Value)>(); while (enumerator.MoveNext()) { - headers.Add(enumerator.Current); + headers.Add(CreateHeaderResult(enumerator.HPackStaticTableId, enumerator.Current.Key, enumerator.Current.Value)); } return headers.ToArray(); } + + private static (int HPackStaticTableId, string Key, string Value) CreateHeaderResult(int hPackStaticTableId, string key, string value) + { + return (hPackStaticTableId, key, value); + } } }