public void BeginEncodeHeaders_MaxHeaderTableSizeUpdated_SizeUpdateInHeaders() { Span <byte> buffer = new byte[1024 * 16]; var hpackEncoder = new DynamicHPackEncoder(); hpackEncoder.UpdateMaxHeaderTableSize(100); var enumerator = new Http2HeadersEnumerator(); // First request enumerator.Initialize(new Dictionary <string, StringValues>()); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out var length)); Assert.Equal(2, length); const byte DynamicTableSizeUpdateMask = 0xe0; var integerDecoder = new IntegerDecoder(); Assert.False(integerDecoder.BeginTryDecode((byte)(buffer[0] & ~DynamicTableSizeUpdateMask), prefixLength: 5, out _)); Assert.True(integerDecoder.TryDecode(buffer[1], out var result)); Assert.Equal(100, result); // Second request enumerator.Initialize(new Dictionary <string, StringValues>()); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out length)); Assert.Equal(0, length); }
public void Initialize_ChangeHeadersSource_EnumeratorUsesNewSource() { var responseHeaders = new HttpResponseHeaders(); responseHeaders.Append("Name1", "Value1"); responseHeaders.Append("Name2", "Value2-1"); responseHeaders.Append("Name2", "Value2-2"); var e = new Http2HeadersEnumerator(); e.Initialize(responseHeaders); 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 { HeaderGrpcStatus = "1" }; responseTrailers.Append("Name1", "Value1"); responseTrailers.Append("Name2", "Value2-1"); responseTrailers.Append("Name2", "Value2-2"); e.Initialize(responseTrailers); 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()); }
public void KnownSingleValueResponseHeaders() { _enumerator.Initialize(_knownSingleValueResponseHeaders); if (_enumerator.MoveNext()) { } }
public void BeginEncodeHeaders_CacheControlPrivate_NewIndexValue() { Span <byte> buffer = new byte[1024 * 16]; var headers = (IHeaderDictionary) new HttpResponseHeaders(); headers.CacheControl = "private"; var enumerator = new Http2HeadersEnumerator(); enumerator.Initialize(headers); var hpackEncoder = new DynamicHPackEncoder(); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length)); var result = buffer.Slice(5, length - 5).ToArray(); var hex = BitConverter.ToString(result); Assert.Equal("58-07-70-72-69-76-61-74-65", hex); var statusHeader = GetHeaderEntry(hpackEncoder, 0); Assert.Equal("Cache-Control", statusHeader.Name); Assert.Equal("private", statusHeader.Value); }
public void BeginEncodeHeaders_ExcludedHeaders_NotAddedToTable(string headerName, bool neverIndex) { Span <byte> buffer = new byte[1024 * 16]; var headers = new HttpResponseHeaders(); headers.Append(headerName, "1"); var enumerator = new Http2HeadersEnumerator(); enumerator.Initialize(headers); var hpackEncoder = new DynamicHPackEncoder(maxHeaderTableSize: Http2PeerSettings.DefaultHeaderTableSize); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(hpackEncoder, enumerator, buffer, out _)); if (neverIndex) { Assert.Equal(0x10, buffer[0] & 0x10); } else { Assert.Equal(0, buffer[0] & 0x40); } Assert.Empty(GetHeaderEntries(hpackEncoder)); }
public void CanIterateOverResponseTrailers() { var responseTrailers = new HttpResponseTrailers { ContentLength = 9, HeaderETag = "ETag!" }; responseTrailers.Append("Name1", "Value1"); responseTrailers.Append("Name2", "Value2-1"); responseTrailers.Append("Name2", "Value2-2"); responseTrailers.Append("Name3", "Value3"); var e = new Http2HeadersEnumerator(); e.Initialize(responseTrailers); var headers = GetNormalizedHeaders(e); Assert.Equal(new[] { CreateHeaderResult(H2StaticTable.ETag, "ETag", "ETag!"), CreateHeaderResult(-1, "Name1", "Value1"), CreateHeaderResult(-1, "Name2", "Value2-1"), CreateHeaderResult(-1, "Name2", "Value2-2"), CreateHeaderResult(-1, "Name3", "Value3"), }, headers); }
public void CanIterateOverResponseTrailers() { var responseTrailers = new HttpResponseTrailers { ContentLength = 9, HeaderETag = "ETag!" }; responseTrailers.Append("Name1", "Value1"); responseTrailers.Append("Name2", "Value2-1"); responseTrailers.Append("Name2", "Value2-2"); responseTrailers.Append("Name3", "Value3"); var e = new Http2HeadersEnumerator(); e.Initialize(responseTrailers); var headers = GetNormalizedHeaders(e); Assert.Equal(new[] { new KeyValuePair <string, string>("ETag", "ETag!"), new KeyValuePair <string, string>("Name1", "Value1"), new KeyValuePair <string, string>("Name2", "Value2-1"), new KeyValuePair <string, string>("Name2", "Value2-2"), new KeyValuePair <string, string>("Name3", "Value3"), }, headers); }
public void CanIterateOverResponseHeaders() { var responseHeaders = new HttpResponseHeaders { ContentLength = 9, HeaderAcceptRanges = "AcceptRanges!", HeaderAge = new StringValues(new[] { "1", "2" }), HeaderDate = "Date!" }; responseHeaders.Append("Name1", "Value1"); responseHeaders.Append("Name2", "Value2-1"); responseHeaders.Append("Name2", "Value2-2"); responseHeaders.Append("Name3", "Value3"); var e = new Http2HeadersEnumerator(); e.Initialize(responseHeaders); var headers = GetNormalizedHeaders(e); Assert.Equal(new[] { new KeyValuePair <string, string>("Date", "Date!"), new KeyValuePair <string, string>("Accept-Ranges", "AcceptRanges!"), new KeyValuePair <string, string>("Age", "1"), new KeyValuePair <string, string>("Age", "2"), new KeyValuePair <string, string>("Content-Length", "9"), new KeyValuePair <string, string>("Name1", "Value1"), new KeyValuePair <string, string>("Name2", "Value2-1"), new KeyValuePair <string, string>("Name2", "Value2-2"), new KeyValuePair <string, string>("Name3", "Value3"), }, headers); }
public void CanIterateOverResponseHeaders() { var responseHeaders = (IHeaderDictionary) new HttpResponseHeaders(); responseHeaders.ContentLength = 9; responseHeaders.AcceptRanges = "AcceptRanges!"; responseHeaders.Age = new StringValues(new[] { "1", "2" }); responseHeaders.Date = "Date!"; responseHeaders.GrpcEncoding = "Identity!"; responseHeaders.Append("Name1", "Value1"); responseHeaders.Append("Name2", "Value2-1"); responseHeaders.Append("Name2", "Value2-2"); responseHeaders.Append("Name3", "Value3"); var e = new Http2HeadersEnumerator(); e.Initialize(responseHeaders); var headers = GetNormalizedHeaders(e); Assert.Equal(new[] { CreateHeaderResult(H2StaticTable.Date, "Date", "Date!"), CreateHeaderResult(H2StaticTable.AcceptRanges, "Accept-Ranges", "AcceptRanges!"), CreateHeaderResult(H2StaticTable.Age, "Age", "1"), CreateHeaderResult(H2StaticTable.Age, "Age", "2"), CreateHeaderResult(-1, "Grpc-Encoding", "Identity!"), 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); }
private static Http2HeadersEnumerator GetHeadersEnumerator(IEnumerable <KeyValuePair <string, string> > headers) { var groupedHeaders = headers .GroupBy(k => k.Key) .ToDictionary(g => g.Key, g => new StringValues(g.Select(gg => gg.Value).ToArray())); var enumerator = new Http2HeadersEnumerator(); enumerator.Initialize(groupedHeaders); return(enumerator); }
public void BeginEncodeHeaders_HeaderExceedHeaderTableSize_NoIndexAndNoHeaderEntry() { Span <byte> buffer = new byte[1024 * 16]; var headers = new HttpResponseHeaders(); headers.Append("x-Custom", new string('!', (int)Http2PeerSettings.DefaultHeaderTableSize)); var enumerator = new Http2HeadersEnumerator(); enumerator.Initialize(headers); var hpackEncoder = new DynamicHPackEncoder(); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(200, hpackEncoder, enumerator, buffer, out var length)); Assert.Empty(GetHeaderEntries(hpackEncoder)); }
public void BeginEncodeHeaders_Status302_NewIndexValue() { Span <byte> buffer = new byte[1024 * 16]; var headers = new HttpResponseHeaders(); var enumerator = new Http2HeadersEnumerator(); enumerator.Initialize(headers); var hpackEncoder = new DynamicHPackEncoder(); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length)); var result = buffer.Slice(0, length).ToArray(); var hex = BitConverter.ToString(result); Assert.Equal("48-03-33-30-32", hex); var statusHeader = GetHeaderEntry(hpackEncoder, 0); Assert.Equal(":status", statusHeader.Name); Assert.Equal("302", statusHeader.Value); }
public void BeginEncodeHeaders_MaxHeaderTableSizeExceeded_EvictionsToFit() { // Test follows example https://tools.ietf.org/html/rfc7541#appendix-C.5 Span <byte> buffer = new byte[1024 * 16]; var headers = (IHeaderDictionary) new HttpResponseHeaders(); headers.CacheControl = "private"; headers.Date = "Mon, 21 Oct 2013 20:13:21 GMT"; headers.Location = "https://www.example.com"; var enumerator = new Http2HeadersEnumerator(); var hpackEncoder = new DynamicHPackEncoder(maxHeaderTableSize: 256); // First response enumerator.Initialize(headers); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(302, hpackEncoder, enumerator, buffer, out var length)); var result = buffer.Slice(0, length).ToArray(); var hex = BitConverter.ToString(result); Assert.Equal( "48-03-33-30-32-61-1D-4D-6F-6E-2C-20-32-31-20-4F-" + "63-74-20-32-30-31-33-20-32-30-3A-31-33-3A-32-31-" + "20-47-4D-54-58-07-70-72-69-76-61-74-65-6E-17-68-" + "74-74-70-73-3A-2F-2F-77-77-77-2E-65-78-61-6D-70-" + "6C-65-2E-63-6F-6D", hex); var entries = GetHeaderEntries(hpackEncoder); Assert.Collection(entries, e => { Assert.Equal("Location", e.Name); Assert.Equal("https://www.example.com", e.Value); Assert.Equal(63u, e.Size); }, e => { Assert.Equal("Cache-Control", e.Name); Assert.Equal("private", e.Value); Assert.Equal(52u, e.Size); }, e => { Assert.Equal("Date", e.Name); Assert.Equal("Mon, 21 Oct 2013 20:13:21 GMT", e.Value); Assert.Equal(65u, e.Size); }, e => { Assert.Equal(":status", e.Name); Assert.Equal("302", e.Value); Assert.Equal(42u, e.Size); }); Assert.Equal(222u, hpackEncoder.TableSize); // Second response enumerator.Initialize(headers); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(307, hpackEncoder, enumerator, buffer, out length)); result = buffer.Slice(0, length).ToArray(); hex = BitConverter.ToString(result); Assert.Equal("48-03-33-30-37-C1-C0-BF", hex); entries = GetHeaderEntries(hpackEncoder); Assert.Collection(entries, e => { Assert.Equal(":status", e.Name); Assert.Equal("307", e.Value); Assert.Equal(42u, e.Size); }, e => { Assert.Equal("Location", e.Name); Assert.Equal("https://www.example.com", e.Value); Assert.Equal(63u, e.Size); }, e => { Assert.Equal("Cache-Control", e.Name); Assert.Equal("private", e.Value); Assert.Equal(52u, e.Size); }, e => { Assert.Equal("Date", e.Name); Assert.Equal("Mon, 21 Oct 2013 20:13:21 GMT", e.Value); Assert.Equal(65u, e.Size); }); Assert.Equal(222u, hpackEncoder.TableSize); // Third response headers.Date = "Mon, 21 Oct 2013 20:13:22 GMT"; headers.ContentEncoding = "gzip"; headers.SetCookie = "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"; enumerator.Initialize(headers); Assert.True(HPackHeaderWriter.BeginEncodeHeaders(200, hpackEncoder, enumerator, buffer, out length)); result = buffer.Slice(0, length).ToArray(); hex = BitConverter.ToString(result); Assert.Equal( "88-61-1D-4D-6F-6E-2C-20-32-31-20-4F-63-74-20-32-" + "30-31-33-20-32-30-3A-31-33-3A-32-32-20-47-4D-54-" + "C1-5A-04-67-7A-69-70-C1-1F-28-38-66-6F-6F-3D-41-" + "53-44-4A-4B-48-51-4B-42-5A-58-4F-51-57-45-4F-50-" + "49-55-41-58-51-57-45-4F-49-55-3B-20-6D-61-78-2D-" + "61-67-65-3D-33-36-30-30-3B-20-76-65-72-73-69-6F-" + "6E-3D-31", hex); entries = GetHeaderEntries(hpackEncoder); Assert.Collection(entries, e => { Assert.Equal("Content-Encoding", e.Name); Assert.Equal("gzip", e.Value); Assert.Equal(52u, e.Size); }, e => { Assert.Equal("Date", e.Name); Assert.Equal("Mon, 21 Oct 2013 20:13:22 GMT", e.Value); Assert.Equal(65u, e.Size); }, e => { Assert.Equal(":status", e.Name); Assert.Equal("307", e.Value); Assert.Equal(42u, e.Size); }, e => { Assert.Equal("Location", e.Name); Assert.Equal("https://www.example.com", e.Value); Assert.Equal(63u, e.Size); }); Assert.Equal(222u, hpackEncoder.TableSize); }
public void BeginEncodeHeaders_KnownHeaders() { _http2HeadersEnumerator.Initialize(_knownResponseHeaders); HPackHeaderWriter.BeginEncodeHeaders(_hpackEncoder, _http2HeadersEnumerator, _buffer, out _); }