public void GlobalSetup() { _memoryPool = SlabMemoryPoolFactory.Create(); var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false); _pipe = new Pipe(options); _httpRequestHeaders = new HttpRequestHeaders(); _httpRequestHeaders.Append(HeaderNames.Method, new StringValues("GET")); _httpRequestHeaders.Append(HeaderNames.Path, new StringValues("/")); _httpRequestHeaders.Append(HeaderNames.Scheme, new StringValues("http")); _httpRequestHeaders.Append(HeaderNames.Authority, new StringValues("localhost:80")); _hpackEncoder = new HPackEncoder(); _headersBuffer = new byte[1024 * 16]; var serviceContext = new ServiceContext { DateHeaderValueManager = new DateHeaderValueManager(), ServerOptions = new KestrelServerOptions(), Log = new KestrelTrace(NullLogger.Instance), SystemClock = new MockSystemClock() }; serviceContext.ServerOptions.Limits.Http2.MaxStreamsPerConnection = int.MaxValue; serviceContext.DateHeaderValueManager.OnHeartbeat(default);
public void CanSpecifyEncodingBasedOnHeaderName() { const string headerValue = "Hello \u03a0"; var acceptNameBytes = Encoding.ASCII.GetBytes(HeaderNames.Accept); var cookieNameBytes = Encoding.ASCII.GetBytes(HeaderNames.Cookie); var headerValueBytes = Encoding.UTF8.GetBytes(headerValue); var headers = new HttpRequestHeaders(encodingSelector: headerName => { // For known headers, the HeaderNames value is passed in. if (ReferenceEquals(headerName, HeaderNames.Accept)) { return(Encoding.GetEncoding("ASCII", EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback)); } return(Encoding.UTF8); }); Assert.Throws <InvalidOperationException>(() => headers.Append(acceptNameBytes, headerValueBytes)); headers.Append(cookieNameBytes, headerValueBytes); headers.OnHeadersComplete(); var parsedAcceptHeaderValue = ((IHeaderDictionary)headers)[HeaderNames.Accept].ToString(); var parsedCookieHeaderValue = ((IHeaderDictionary)headers)[HeaderNames.Cookie].ToString(); Assert.Empty(parsedAcceptHeaderValue); Assert.Equal(headerValue, parsedCookieHeaderValue); }
private static (string PrevHeaderValue, string NextHeaderValue) GetHeaderValues(HttpRequestHeaders headers, string prevName, string nextName, string prevValue, string nextValue) { headers.Reset(); var headerName = Encoding.ASCII.GetBytes(prevName).AsSpan(); var prevSpan = Encoding.UTF8.GetBytes(prevValue).AsSpan(); headers.Append(headerName, prevSpan); headers.OnHeadersComplete(); var prevHeaderValue = ((IHeaderDictionary)headers)[prevName].ToString(); headers.Reset(); if (nextValue != null) { headerName = Encoding.ASCII.GetBytes(prevName).AsSpan(); var nextSpan = Encoding.UTF8.GetBytes(nextValue).AsSpan(); headers.Append(headerName, nextSpan); } headers.OnHeadersComplete(); var newHeaderValue = ((IHeaderDictionary)headers)[nextName].ToString(); return(prevHeaderValue, newHeaderValue); }
public void GlobalSetup() { _memoryPool = SlabMemoryPoolFactory.Create(); _httpFrame = new Http2Frame(); _responseData = new string('!', ResponseDataLength); var options = new PipeOptions(_memoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false); _connectionPair = DuplexPipe.CreateConnectionPair(options, options); _httpRequestHeaders = new HttpRequestHeaders(); _httpRequestHeaders.Append(HeaderNames.Method, new StringValues("GET")); _httpRequestHeaders.Append(HeaderNames.Path, new StringValues("/")); _httpRequestHeaders.Append(HeaderNames.Scheme, new StringValues("http")); _httpRequestHeaders.Append(HeaderNames.Authority, new StringValues("localhost:80")); _headersBuffer = new byte[1024 * 16]; var serviceContext = new ServiceContext { DateHeaderValueManager = new DateHeaderValueManager(), ServerOptions = new KestrelServerOptions(), Log = new KestrelTrace(NullLogger.Instance), SystemClock = new MockSystemClock() }; serviceContext.DateHeaderValueManager.OnHeartbeat(default);
public void ValueReuseLatin1NotConfusedForUtf16AndStillRejected(bool reuseValue, KnownHeader header) { var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue); var headerValue = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1 for (var i = 0; i < headerValue.Length; i++) { headerValue[i] = 'a'; } for (var i = 0; i < headerValue.Length; i++) { // Set non-ascii Latin char that is valid Utf16 when widened; but not a valid utf8 -> utf16 conversion. headerValue[i] = '\u00a3'; for (var mode = 0; mode <= 1; mode++) { string headerValueUtf16Latin1CrossOver; if (mode == 0) { // Full length headerValueUtf16Latin1CrossOver = new string(headerValue); } else { // Truncated length (to ensure different paths from changing lengths in matching) headerValueUtf16Latin1CrossOver = new string(headerValue.AsSpan().Slice(0, i + 1)); } headers.Reset(); var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var prevSpan = Encoding.UTF8.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan(); headers.Append(headerName, prevSpan); headers.OnHeadersComplete(); var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.Equal(headerValueUtf16Latin1CrossOver, prevHeaderValue); Assert.NotSame(headerValueUtf16Latin1CrossOver, prevHeaderValue); headers.Reset(); Assert.Throws <InvalidOperationException>(() => { var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var nextSpan = Encoding.Latin1.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan(); Assert.False(nextSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver))); headers.Append(headerName, nextSpan); }); } // Reset back to Ascii headerValue[i] = 'a'; } }
public void Latin1ValuesAcceptedInLatin1ModeButNotReused(bool reuseValue, KnownHeader header) { var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue, _ => Encoding.Latin1); var headerValue = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1 for (var i = 0; i < headerValue.Length; i++) { headerValue[i] = 'a'; } for (var i = 0; i < headerValue.Length; i++) { // Set non-ascii Latin char that is valid Utf16 when widened; but not a valid utf8 -> utf16 conversion. headerValue[i] = '\u00a3'; for (var mode = 0; mode <= 1; mode++) { string headerValueUtf16Latin1CrossOver; if (mode == 0) { // Full length headerValueUtf16Latin1CrossOver = new string(headerValue); } else { // Truncated length (to ensure different paths from changing lengths in matching) headerValueUtf16Latin1CrossOver = new string(headerValue.AsSpan().Slice(0, i + 1)); } var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var latinValueSpan = Encoding.Latin1.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan(); Assert.False(latinValueSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver))); headers.Reset(); headers.Append(headerName, latinValueSpan); headers.OnHeadersComplete(); var parsedHeaderValue1 = ((IHeaderDictionary)headers)[header.Name].ToString(); headers.Reset(); headers.Append(headerName, latinValueSpan); headers.OnHeadersComplete(); var parsedHeaderValue2 = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.Equal(headerValueUtf16Latin1CrossOver, parsedHeaderValue1); Assert.Equal(parsedHeaderValue1, parsedHeaderValue2); Assert.NotSame(parsedHeaderValue1, parsedHeaderValue2); } // Reset back to Ascii headerValue[i] = 'a'; } }
public void NullCharactersRejectedInUTF8AndLatin1Mode(bool useLatin1, KnownHeader header) { var headers = new HttpRequestHeaders(encodingSelector: useLatin1 ? _ => Encoding.Latin1 : (Func <string, Encoding>)null); var valueArray = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1 for (var i = 0; i < valueArray.Length; i++) { valueArray[i] = 'a'; } for (var i = 1; i < valueArray.Length; i++) { // Set non-ascii Latin char that is valid Utf16 when widened; but not a valid utf8 -> utf16 conversion. valueArray[i] = '\0'; string valueString = new string(valueArray); headers.Reset(); Assert.Throws <InvalidOperationException>(() => { var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var valueSpan = Encoding.ASCII.GetBytes(valueString).AsSpan(); headers.Append(headerName, valueSpan); }); valueArray[i] = 'a'; } }
public void MultiValueReuseEmptyAfterReset(bool reuseValue, KnownHeader header) { const string HeaderValue1 = "Hello1"; const string HeaderValue2 = "Hello2"; var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue); var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var prevSpan1 = Encoding.UTF8.GetBytes(HeaderValue1).AsSpan(); var prevSpan2 = Encoding.UTF8.GetBytes(HeaderValue2).AsSpan(); headers.Append(headerName, prevSpan1); headers.Append(headerName, prevSpan2); headers.OnHeadersComplete(); var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name]; Assert.Equal(2, prevHeaderValue.Count); Assert.NotEqual(string.Empty, prevHeaderValue.ToString()); Assert.Single(headers); var count = headers.Count; Assert.Equal(1, count); headers.Reset(); // Empty after reset var nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.NotNull(nextHeaderValue); Assert.Equal(string.Empty, nextHeaderValue); Assert.Empty(headers); count = headers.Count; Assert.Equal(0, count); headers.OnHeadersComplete(); // Still empty after complete nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.NotNull(nextHeaderValue); Assert.Equal(string.Empty, nextHeaderValue); Assert.Empty(headers); count = headers.Count; Assert.Equal(0, count); }
public void AppendThrowsWhenHeaderNameContainsNonASCIICharacters() { var headers = new HttpRequestHeaders(); const string key = "\u00141\u00F3d\017c"; var encoding = Encoding.GetEncoding("iso-8859-1"); var exception = Assert.Throws<BadHttpRequestException>( () => headers.Append(encoding.GetBytes(key), Encoding.ASCII.GetBytes("value"))); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); }
public void AppendThrowsWhenHeaderNameContainsNonASCIICharacters() { var headers = new HttpRequestHeaders(); const string key = "\u00141\u00F3d\017c"; #pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws <BadHttpRequestException>( #pragma warning restore CS0618 // Type or member is obsolete () => headers.Append(Encoding.Latin1.GetBytes(key), Encoding.ASCII.GetBytes("value"))); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); }
public void CanSpecifyEncodingForContentLength() { var contentLengthNameBytes = Encoding.ASCII.GetBytes(HeaderNames.ContentLength); // Always 32 bits per code point, so not a superset of ASCII var contentLengthValueBytes = Encoding.UTF32.GetBytes("1337"); var headers = new HttpRequestHeaders(encodingSelector: _ => Encoding.UTF32); headers.Append(contentLengthNameBytes, contentLengthValueBytes); headers.OnHeadersComplete(); Assert.Equal(1337, headers.ContentLength); Assert.Throws <InvalidOperationException>(() => new HttpRequestHeaders().Append(contentLengthNameBytes, contentLengthValueBytes)); }
public void ValueReuseEmptyAfterReset(bool reuseValue, KnownHeader header) { const string HeaderValue = "Hello"; var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue); var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan(); var prevSpan = Encoding.UTF8.GetBytes(HeaderValue).AsSpan(); headers.Append(headerName, prevSpan, checkForNewlineChars: false); headers.OnHeadersComplete(); var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.NotNull(prevHeaderValue); Assert.NotEqual(string.Empty, prevHeaderValue); Assert.Equal(HeaderValue, prevHeaderValue); Assert.NotSame(HeaderValue, prevHeaderValue); Assert.Single(headers); var count = headers.Count; Assert.Equal(1, count); headers.Reset(); // Empty after reset var nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.NotNull(nextHeaderValue); Assert.Equal(string.Empty, nextHeaderValue); Assert.NotEqual(HeaderValue, nextHeaderValue); Assert.Empty(headers); count = headers.Count; Assert.Equal(0, count); headers.OnHeadersComplete(); // Still empty after complete nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString(); Assert.NotNull(nextHeaderValue); Assert.Equal(string.Empty, nextHeaderValue); Assert.NotEqual(HeaderValue, nextHeaderValue); Assert.Empty(headers); count = headers.Count; Assert.Equal(0, count); }