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 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 EntriesCanBeEnumeratedAfterResets() { HttpRequestHeaders headers = new HttpRequestHeaders(); EnumerateEntries((IHeaderDictionary)headers); headers.Reset(); EnumerateEntries((IDictionary <string, StringValues>)headers); headers.Reset(); EnumerateEntries((IHeaderDictionary)headers); headers.Reset(); EnumerateEntries((IDictionary <string, StringValues>)headers); }
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 EnumeratorReusedAfterReset() { HttpRequestHeaders headers = new HttpRequestHeaders(); IEnumerable <KeyValuePair <string, StringValues> > enumerable = headers; var enumerator0 = enumerable.GetEnumerator(); headers.Reset(); var enumerator1 = enumerable.GetEnumerator(); Assert.Same(enumerator0, enumerator1); }
public void ClearPseudoRequestHeadersPlusResetClearsHeaderReferenceValue() { const BindingFlags privateFlags = BindingFlags.NonPublic | BindingFlags.Instance; HttpRequestHeaders headers = new HttpRequestHeaders(reuseHeaderValues: false); headers.HeaderMethod = "GET"; headers.ClearPseudoRequestHeaders(); headers.Reset(); // Hacky but required because header references is private. var headerReferences = typeof(HttpRequestHeaders).GetField("_headers", privateFlags).GetValue(headers); var methodValue = (StringValues)headerReferences.GetType().GetField("_Method").GetValue(headerReferences); Assert.Equal(StringValues.Empty, methodValue); }
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 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); }