public static string GetHeaderValue(string name, char[] array, int startIndex, int length) { Debug.Assert(name != null); CharArrayHelpers.DebugAssertArrayInputs(array, startIndex, length); if (length == 0) { return(string.Empty); } // If it's a known header value, use the known value instead of allocating a new string. // Do a really quick reference equals check to see if name is the same object as // HttpKnownHeaderNames.ContentEncoding, in which case the value is very likely to // be either "gzip" or "deflate". if (ReferenceEquals(name, ContentEncoding)) { if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(Gzip, array, startIndex, length)) { return(Gzip); } else if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(Deflate, array, startIndex, length)) { return(Deflate); } } return(new string(array, startIndex, length)); }
public void EqualsOrdinalAsciiIgnoreCase_ComparingVariousInputsBothWays_ReturnsExpected(string leftString, string rightString, bool expected) { char[] left = leftString.ToCharArray(); char[] right = rightString.ToCharArray(); Assert.Equal(expected, CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(leftString, right, 0, right.Length)); Assert.Equal(expected, CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(rightString, left, 0, left.Length)); }
public void EqualsOrdinalAsciiIgnoreCase_ComparingLowerAndUpperCaseAsciiChars_ReturnsTrue() { for (char c = '\0'; c <= 127; c++) { string lowerString = c.ToString(); string upperString = char.ToUpperInvariant(c).ToString(); char[] lowerCharArray = new char[] { c }; char[] upperCharArray = new char[] { char.ToUpperInvariant(c) }; Assert.True(CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(lowerString, lowerCharArray, 0, 1)); Assert.True(CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(upperString, lowerCharArray, 0, 1)); Assert.True(CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(lowerString, upperCharArray, 0, 1)); Assert.True(CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase(upperString, upperCharArray, 0, 1)); } }
public static HttpResponseMessage CreateResponseMessage( WinHttpRequestState state, bool doManualDecompressionCheck) { HttpRequestMessage request = state.RequestMessage; SafeWinHttpHandle requestHandle = state.RequestHandle; CookieUsePolicy cookieUsePolicy = state.Handler.CookieUsePolicy; CookieContainer cookieContainer = state.Handler.CookieContainer; var response = new HttpResponseMessage(); bool stripEncodingHeaders = false; // Create a single buffer to use for all subsequent WinHttpQueryHeaders string interop calls. // This buffer is the length needed for WINHTTP_QUERY_RAW_HEADERS_CRLF, which includes the status line // and all headers separated by CRLF, so it should be large enough for any individual status line or header queries. int bufferLength = GetResponseHeaderCharBufferLength(requestHandle, Interop.WinHttp.WINHTTP_QUERY_RAW_HEADERS_CRLF); char[] buffer = ArrayPool <char> .Shared.Rent(bufferLength); try { // Get HTTP version, status code, reason phrase from the response headers. if (IsResponseHttp2(requestHandle)) { response.Version = WinHttpHandler.HttpVersion20; } else { int versionLength = GetResponseHeader(requestHandle, Interop.WinHttp.WINHTTP_QUERY_VERSION, buffer); response.Version = CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase("HTTP/1.1", buffer, 0, versionLength) ? HttpVersionInternal.Version11 : CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase("HTTP/1.0", buffer, 0, versionLength) ? HttpVersionInternal.Version10 : WinHttpHandler.HttpVersionUnknown; } response.StatusCode = (HttpStatusCode)GetResponseHeaderNumberInfo( requestHandle, Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE); int reasonPhraseLength = GetResponseHeader(requestHandle, Interop.WinHttp.WINHTTP_QUERY_STATUS_TEXT, buffer); response.ReasonPhrase = reasonPhraseLength > 0 ? GetReasonPhrase(response.StatusCode, buffer, reasonPhraseLength) : string.Empty; // Create response stream and wrap it in a StreamContent object. var responseStream = new WinHttpResponseStream(requestHandle, state); state.RequestHandle = null; // ownership successfully transfered to WinHttpResponseStram. Stream decompressedStream = responseStream; if (doManualDecompressionCheck) { int contentEncodingStartIndex = 0; int contentEncodingLength = GetResponseHeader( requestHandle, Interop.WinHttp.WINHTTP_QUERY_CONTENT_ENCODING, buffer); CharArrayHelpers.Trim(buffer, ref contentEncodingStartIndex, ref contentEncodingLength); if (contentEncodingLength > 0) { if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase( EncodingNameGzip, buffer, contentEncodingStartIndex, contentEncodingLength)) { decompressedStream = new GZipStream(responseStream, CompressionMode.Decompress); stripEncodingHeaders = true; } else if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase( EncodingNameDeflate, buffer, contentEncodingStartIndex, contentEncodingLength)) { decompressedStream = new DeflateStream(responseStream, CompressionMode.Decompress); stripEncodingHeaders = true; } } } response.Content = new NoWriteNoSeekStreamContent(decompressedStream); response.RequestMessage = request; // Parse raw response headers and place them into response message. ParseResponseHeaders(requestHandle, response, buffer, stripEncodingHeaders); if (response.RequestMessage.Method != HttpMethod.Head) { state.ExpectedBytesToRead = response.Content.Headers.ContentLength; } return(response); } finally { ArrayPool <char> .Shared.Return(buffer); } }
public static HttpResponseMessage CreateResponseMessage( WinHttpRequestState state, bool doManualDecompressionCheck) { HttpRequestMessage request = state.RequestMessage; SafeWinHttpHandle requestHandle = state.RequestHandle; CookieUsePolicy cookieUsePolicy = state.Handler.CookieUsePolicy; CookieContainer cookieContainer = state.Handler.CookieContainer; var response = new HttpResponseMessage(); bool stripEncodingHeaders = false; // Create a single buffer to use for all subsequent WinHttpQueryHeaders string interop calls. // This buffer is the length needed for WINHTTP_QUERY_RAW_HEADERS_CRLF, which includes the status line // and all headers separated by CRLF, so it should be large enough for any individual status line or header queries. int bufferLength = GetResponseHeaderCharBufferLength(requestHandle, Interop.WinHttp.WINHTTP_QUERY_RAW_HEADERS_CRLF); char[] buffer = new char[bufferLength]; // Get HTTP version, status code, reason phrase from the response headers. int versionLength = GetResponseHeader(requestHandle, Interop.WinHttp.WINHTTP_QUERY_VERSION, buffer); response.Version = CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase("HTTP/1.1", buffer, 0, versionLength) ? HttpVersion.Version11 : CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase("HTTP/1.0", buffer, 0, versionLength) ? HttpVersion.Version10 : HttpVersion.Unknown; response.StatusCode = (HttpStatusCode)GetResponseHeaderNumberInfo( requestHandle, Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE); int reasonPhraseLength = GetResponseHeader(requestHandle, Interop.WinHttp.WINHTTP_QUERY_STATUS_TEXT, buffer); response.ReasonPhrase = reasonPhraseLength > 0 ? GetReasonPhrase(response.StatusCode, buffer, reasonPhraseLength) : string.Empty; // Create response stream and wrap it in a StreamContent object. var responseStream = new WinHttpResponseStream(requestHandle, state); state.RequestHandle = null; // ownership successfully transfered to WinHttpResponseStram. Stream decompressedStream = responseStream; if (doManualDecompressionCheck) { int contentEncodingStartIndex = 0; int contentEncodingLength = GetResponseHeader( requestHandle, Interop.WinHttp.WINHTTP_QUERY_CONTENT_ENCODING, buffer); CharArrayHelpers.Trim(buffer, ref contentEncodingStartIndex, ref contentEncodingLength); if (contentEncodingLength > 0) { if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase( EncodingNameGzip, buffer, contentEncodingStartIndex, contentEncodingLength)) { decompressedStream = new GZipStream(responseStream, CompressionMode.Decompress); stripEncodingHeaders = true; } else if (CharArrayHelpers.EqualsOrdinalAsciiIgnoreCase( EncodingNameDeflate, buffer, contentEncodingStartIndex, contentEncodingLength)) { decompressedStream = new DeflateStream(responseStream, CompressionMode.Decompress); stripEncodingHeaders = true; } } } #if HTTP_DLL var content = new StreamContent(decompressedStream, state.CancellationToken); #else // TODO: Issue https://github.com/dotnet/corefx/issues/9071 // We'd like to be able to pass state.CancellationToken into the StreamContent so that its // SerializeToStreamAsync method can use it, but that ctor isn't public, nor is there a // SerializeToStreamAsync override that takes a CancellationToken. var content = new StreamContent(decompressedStream); #endif response.Content = content; response.RequestMessage = request; // Parse raw response headers and place them into response message. ParseResponseHeaders(requestHandle, response, buffer, stripEncodingHeaders); if (response.RequestMessage.Method != HttpMethod.Head) { state.ExpectedBytesToRead = response.Content.Headers.ContentLength; } return(response); }