|
14 | 14 | using Microsoft.AspNetCore.Connections;
|
15 | 15 | using Microsoft.AspNetCore.Http;
|
16 | 16 | using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
| 17 | +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; |
17 | 18 | using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
|
18 | 19 | using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
19 | 20 | using Microsoft.AspNetCore.Testing;
|
20 | 21 | using Microsoft.Extensions.Logging;
|
| 22 | +using Microsoft.Extensions.Primitives; |
21 | 23 | using Microsoft.Net.Http.Headers;
|
22 | 24 | using Moq;
|
23 | 25 | using Xunit;
|
@@ -1933,6 +1935,79 @@ await ExpectAsync(Http2FrameType.HEADERS,
|
1933 | 1935 | await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
|
1934 | 1936 | }
|
1935 | 1937 |
|
| 1938 | + [Fact] |
| 1939 | + public async Task HEADERS_ResponseSetsIgnoreIndexAndNeverIndexValues_HeadersParsed() |
| 1940 | + { |
| 1941 | + await InitializeConnectionAsync(c => |
| 1942 | + { |
| 1943 | + c.Response.ContentLength = 0; |
| 1944 | + c.Response.Headers[HeaderNames.SetCookie] = "SetCookie!"; |
| 1945 | + c.Response.Headers[HeaderNames.ContentDisposition] = "ContentDisposition!"; |
| 1946 | + |
| 1947 | + return Task.CompletedTask; |
| 1948 | + }); |
| 1949 | + |
| 1950 | + await StartStreamAsync(1, _browserRequestHeaders, endStream: true); |
| 1951 | + |
| 1952 | + var frame = await ExpectAsync(Http2FrameType.HEADERS, |
| 1953 | + withLength: 90, |
| 1954 | + withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM), |
| 1955 | + withStreamId: 1); |
| 1956 | + |
| 1957 | + var payload = frame.Payload; |
| 1958 | + |
| 1959 | + var handler = new TestHttpHeadersHandler(); |
| 1960 | + |
| 1961 | + var hpackDecoder = new HPackDecoder(); |
| 1962 | + hpackDecoder.Decode(new ReadOnlySequence<byte>(payload), endHeaders: true, handler); |
| 1963 | + hpackDecoder.CompleteDecode(); |
| 1964 | + |
| 1965 | + await StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false); |
| 1966 | + |
| 1967 | + Assert.Equal("200", handler.Headers[":status"]); |
| 1968 | + Assert.Equal("SetCookie!", handler.Headers[HeaderNames.SetCookie]); |
| 1969 | + Assert.Equal("ContentDisposition!", handler.Headers[HeaderNames.ContentDisposition]); |
| 1970 | + Assert.Equal("0", handler.Headers[HeaderNames.ContentLength]); |
| 1971 | + } |
| 1972 | + |
| 1973 | + private class TestHttpHeadersHandler : IHttpHeadersHandler |
| 1974 | + { |
| 1975 | + public readonly Dictionary<string, StringValues> Headers = new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase); |
| 1976 | + |
| 1977 | + public void OnHeader(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value) |
| 1978 | + { |
| 1979 | + var nameString = Encoding.ASCII.GetString(name); |
| 1980 | + var valueString = Encoding.ASCII.GetString(value); |
| 1981 | + |
| 1982 | + if (Headers.TryGetValue(nameString, out var values)) |
| 1983 | + { |
| 1984 | + var l = values.ToList(); |
| 1985 | + l.Add(valueString); |
| 1986 | + |
| 1987 | + Headers[nameString] = new StringValues(l.ToArray()); |
| 1988 | + } |
| 1989 | + else |
| 1990 | + { |
| 1991 | + Headers[nameString] = new StringValues(valueString); |
| 1992 | + } |
| 1993 | + } |
| 1994 | + |
| 1995 | + public void OnHeadersComplete(bool endStream) |
| 1996 | + { |
| 1997 | + throw new NotImplementedException(); |
| 1998 | + } |
| 1999 | + |
| 2000 | + public void OnStaticIndexedHeader(int index) |
| 2001 | + { |
| 2002 | + throw new NotImplementedException(); |
| 2003 | + } |
| 2004 | + |
| 2005 | + public void OnStaticIndexedHeader(int index, ReadOnlySpan<byte> value) |
| 2006 | + { |
| 2007 | + throw new NotImplementedException(); |
| 2008 | + } |
| 2009 | + } |
| 2010 | + |
1936 | 2011 | [Fact]
|
1937 | 2012 | public async Task HEADERS_DisableDynamicHeaderCompression_HeadersNotCompressed()
|
1938 | 2013 | {
|
|
0 commit comments