You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@ -121,6 +121,9 @@
|
||||
<data name="net_http_content_stream_already_read" xml:space="preserve">
|
||||
<value>The stream was already consumed. It cannot be read again.</value>
|
||||
</data>
|
||||
<data name="net_http_winhttp_error" xml:space="preserve">
|
||||
<value>Error {0} calling {1}, '{2}'.</value>
|
||||
</data>
|
||||
<data name="PlatformNotSupported_WinHttpHandler" xml:space="preserve">
|
||||
<value>WinHttpHandler is only supported on .NET Framework and .NET Core runtimes on Windows. It is not supported for Windows Store Applications (UWP) or Unix platforms.</value>
|
||||
</data>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<!-- Although we have a NS configuration, the actual UWP implementation is a shim over WinRT: so just validate against OneCore -->
|
||||
<UWPCompatible>false</UWPCompatible>
|
||||
<IncludeDllSafeSearchPathAttribute>true</IncludeDllSafeSearchPathAttribute>
|
||||
<ILLinkClearInitLocals>true</ILLinkClearInitLocals>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
|
||||
@ -42,6 +43,7 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Buffers" />
|
||||
<Reference Include="System.Diagnostics.DiagnosticSource" />
|
||||
<Reference Include="System.Memory" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'net46' OR '$(TargetGroup)' == 'netfx'">
|
||||
<Reference Include="mscorlib" />
|
||||
|
@ -23,7 +23,6 @@
|
||||
<CompileItem Include="$(CommonPath)\System\Net\UriScheme.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Net\Http\HttpHandlerDefaults.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Net\Http\NoWriteNoSeekStreamContent.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Net\Http\WinHttpException.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Net\Security\CertificateHelper.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Net\Security\CertificateHelper.Windows.cs" />
|
||||
<CompileItem Include="$(CommonPath)\System\Runtime\ExceptionServices\ExceptionStackTrace.cs" />
|
||||
@ -33,6 +32,7 @@
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpCertificateHelper.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpChannelBinding.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpCookieContainerAdapter.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpException.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpHandler.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpRequestCallback.cs" />
|
||||
<CompileItem Include="$(MSBuildThisFileDirectory)\System\Net\Http\WinHttpRequestState.cs" />
|
||||
|
@ -102,7 +102,7 @@ namespace System.Net.Http
|
||||
// But we can validate with assert.
|
||||
Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);
|
||||
|
||||
serverAuthScheme = ChooseAuthScheme(supportedSchemes);
|
||||
serverAuthScheme = ChooseAuthScheme(supportedSchemes, state.RequestMessage.RequestUri, state.ServerCredentials);
|
||||
if (serverAuthScheme != 0)
|
||||
{
|
||||
if (SetWinHttpCredential(
|
||||
@ -155,7 +155,7 @@ namespace System.Net.Http
|
||||
// But we can validate with assert.
|
||||
Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);
|
||||
|
||||
proxyAuthScheme = ChooseAuthScheme(supportedSchemes);
|
||||
proxyAuthScheme = ChooseAuthScheme(supportedSchemes, state.Proxy.GetProxy(state.RequestMessage.RequestUri), proxyCreds);
|
||||
state.RetryRequest = true;
|
||||
break;
|
||||
|
||||
@ -296,7 +296,7 @@ namespace System.Net.Http
|
||||
Interop.WinHttp.WINHTTP_OPTION_AUTOLOGON_POLICY,
|
||||
ref optionData))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetOption));
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,17 +365,22 @@ namespace System.Net.Http
|
||||
password,
|
||||
IntPtr.Zero))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetCredentials));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static uint ChooseAuthScheme(uint supportedSchemes)
|
||||
private static uint ChooseAuthScheme(uint supportedSchemes, Uri uri, ICredentials credentials)
|
||||
{
|
||||
if (credentials == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
foreach (uint authScheme in s_authSchemePriorityOrder)
|
||||
{
|
||||
if ((supportedSchemes & authScheme) != 0)
|
||||
if ((supportedSchemes & authScheme) != 0 && credentials.GetCredential(uri, s_authSchemeStringMapping[authScheme]) != null)
|
||||
{
|
||||
return authScheme;
|
||||
}
|
||||
|
@ -55,11 +55,11 @@ namespace System.Net.Http
|
||||
unsafe
|
||||
{
|
||||
var cppStruct = new Interop.Crypt32.CERT_CHAIN_POLICY_PARA();
|
||||
cppStruct.cbSize = (uint)Marshal.SizeOf<Interop.Crypt32.CERT_CHAIN_POLICY_PARA>();
|
||||
cppStruct.cbSize = (uint)sizeof(Interop.Crypt32.CERT_CHAIN_POLICY_PARA);
|
||||
cppStruct.dwFlags = 0;
|
||||
|
||||
var eppStruct = new Interop.Crypt32.SSL_EXTRA_CERT_CHAIN_POLICY_PARA();
|
||||
eppStruct.cbSize = (uint)Marshal.SizeOf<Interop.Crypt32.SSL_EXTRA_CERT_CHAIN_POLICY_PARA>();
|
||||
eppStruct.cbSize = (uint)sizeof(Interop.Crypt32.SSL_EXTRA_CERT_CHAIN_POLICY_PARA);
|
||||
eppStruct.dwAuthType = Interop.Crypt32.AuthType.AUTHTYPE_SERVER;
|
||||
|
||||
cppStruct.pvExtraPolicyPara = &eppStruct;
|
||||
|
@ -61,7 +61,7 @@ namespace System.Net.Http
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpAddRequestHeaders));
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ namespace System.Net.Http
|
||||
(uint)cookieHeader.Length,
|
||||
Interop.WinHttp.WINHTTP_ADDREQ_FLAG_ADD))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpAddRequestHeaders));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
80
external/corefx/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpException.cs
vendored
Normal file
80
external/corefx/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpException.cs
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.Net.Http
|
||||
{
|
||||
internal class WinHttpException : Win32Exception
|
||||
{
|
||||
public WinHttpException(int error, string message) : base(error, message)
|
||||
{
|
||||
this.HResult = ConvertErrorCodeToHR(error);
|
||||
}
|
||||
|
||||
public WinHttpException(int error, string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
this.HResult = ConvertErrorCodeToHR(error);
|
||||
}
|
||||
|
||||
public static int ConvertErrorCodeToHR(int error)
|
||||
{
|
||||
// This method allows common error detection code to be used by consumers
|
||||
// of HttpClient. This method converts the ErrorCode returned by WinHTTP
|
||||
// to the same HRESULT value as is provided in the .Net Native implementation
|
||||
// of HttpClient under the same error conditions. Clients would access
|
||||
// HttpRequestException.InnerException.HRESULT to discover what caused
|
||||
// the exception.
|
||||
switch (unchecked((uint)error))
|
||||
{
|
||||
case Interop.WinHttp.ERROR_WINHTTP_CONNECTION_ERROR:
|
||||
return unchecked((int)Interop.WinHttp.WININET_E_CONNECTION_RESET);
|
||||
default:
|
||||
// Marshal.GetHRForLastWin32Error can't be used as not all error codes originate from native
|
||||
// code.
|
||||
return Interop.HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ThrowExceptionUsingLastError(string nameOfCalledFunction)
|
||||
{
|
||||
throw CreateExceptionUsingLastError(nameOfCalledFunction);
|
||||
}
|
||||
|
||||
public static WinHttpException CreateExceptionUsingLastError(string nameOfCalledFunction)
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
return CreateExceptionUsingError(lastError, nameOfCalledFunction);
|
||||
}
|
||||
|
||||
public static WinHttpException CreateExceptionUsingError(int error, string nameOfCalledFunction)
|
||||
{
|
||||
var e = new WinHttpException(error, GetErrorMessage(error, nameOfCalledFunction));
|
||||
ExceptionStackTrace.AddCurrentStack(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
public static WinHttpException CreateExceptionUsingError(int error, string nameOfCalledFunction, Exception innerException)
|
||||
{
|
||||
var e = new WinHttpException(error, GetErrorMessage(error, nameOfCalledFunction), innerException);
|
||||
ExceptionStackTrace.AddCurrentStack(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
public static string GetErrorMessage(int error, string nameOfCalledFunction)
|
||||
{
|
||||
Debug.Assert(!string.IsNullOrEmpty(nameOfCalledFunction));
|
||||
|
||||
// Look up specific error message in WINHTTP.DLL since it is not listed in default system resources
|
||||
// and thus can't be found by default .Net interop.
|
||||
IntPtr moduleHandle = Interop.Kernel32.GetModuleHandle(Interop.Libraries.WinHttp);
|
||||
string httpError = Interop.Kernel32.GetMessage(moduleHandle, error);
|
||||
|
||||
return SR.Format(SR.net_http_winhttp_error, error, nameOfCalledFunction, httpError);
|
||||
}
|
||||
}
|
||||
}
|
@ -194,8 +194,6 @@ namespace System.Net.Http
|
||||
|
||||
set
|
||||
{
|
||||
SecurityProtocol.ThrowOnNotAllowed(value, allowNone: true);
|
||||
|
||||
CheckDisposedOrStarted();
|
||||
_sslProtocols = value;
|
||||
}
|
||||
@ -661,7 +659,7 @@ namespace System.Net.Http
|
||||
(uint)requestHeadersBuffer.Length,
|
||||
Interop.WinHttp.WINHTTP_ADDREQ_FLAG_ADD))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpAddRequestHeaders));
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,7 +726,7 @@ namespace System.Net.Http
|
||||
WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: error={0}", lastError);
|
||||
if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
ThrowOnInvalidHandle(sessionHandle);
|
||||
ThrowOnInvalidHandle(sessionHandle, nameof(Interop.WinHttp.WinHttpOpen));
|
||||
}
|
||||
|
||||
// We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support
|
||||
@ -741,7 +739,7 @@ namespace System.Net.Http
|
||||
_proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
|
||||
_proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
|
||||
(int)Interop.WinHttp.WINHTTP_FLAG_ASYNC);
|
||||
ThrowOnInvalidHandle(sessionHandle);
|
||||
ThrowOnInvalidHandle(sessionHandle, nameof(Interop.WinHttp.WinHttpOpen));
|
||||
}
|
||||
|
||||
uint optionAssuredNonBlockingTrue = 1; // TRUE
|
||||
@ -757,7 +755,7 @@ namespace System.Net.Http
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (lastError != Interop.WinHttp.ERROR_WINHTTP_INVALID_OPTION)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpSetOption));
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,7 +786,7 @@ namespace System.Net.Http
|
||||
state.RequestMessage.RequestUri.Host,
|
||||
(ushort)state.RequestMessage.RequestUri.Port,
|
||||
0);
|
||||
ThrowOnInvalidHandle(connectHandle);
|
||||
ThrowOnInvalidHandle(connectHandle, nameof(Interop.WinHttp.WinHttpConnect));
|
||||
connectHandle.SetParentHandle(_sessionHandle);
|
||||
|
||||
// Try to use the requested version if a known/supported version was explicitly requested.
|
||||
@ -821,7 +819,7 @@ namespace System.Net.Http
|
||||
Interop.WinHttp.WINHTTP_NO_REFERER,
|
||||
Interop.WinHttp.WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
flags);
|
||||
ThrowOnInvalidHandle(state.RequestHandle);
|
||||
ThrowOnInvalidHandle(state.RequestHandle, nameof(Interop.WinHttp.WinHttpOpenRequest));
|
||||
state.RequestHandle.SetParentHandle(connectHandle);
|
||||
|
||||
// Set callback function.
|
||||
@ -888,6 +886,16 @@ namespace System.Net.Http
|
||||
|
||||
HttpResponseMessage responseMessage = WinHttpResponseParser.CreateResponseMessage(state, _doManualDecompressionCheck);
|
||||
state.Tcs.TrySetResult(responseMessage);
|
||||
|
||||
// HttpStatusCode cast is needed for 308 Moved Permenantly, which we support but is not included in NetStandard status codes.
|
||||
if (WinHttpTraceHelper.IsTraceEnabled() &&
|
||||
((responseMessage.StatusCode >= HttpStatusCode.MultipleChoices && responseMessage.StatusCode <= HttpStatusCode.SeeOther) ||
|
||||
(responseMessage.StatusCode >= HttpStatusCode.RedirectKeepVerb && responseMessage.StatusCode <= (HttpStatusCode)308)) &&
|
||||
state.RequestMessage.RequestUri.Scheme == Uri.UriSchemeHttps && responseMessage.Headers.Location?.Scheme == Uri.UriSchemeHttp)
|
||||
{
|
||||
WinHttpTraceHelper.Trace("WinHttpHandler.SendAsync: Insecure https to http redirect from {0} to {1} blocked.",
|
||||
state.RequestMessage.RequestUri.ToString(), responseMessage.Headers.Location.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -919,6 +927,18 @@ namespace System.Net.Http
|
||||
uint optionData = 0;
|
||||
SslProtocols sslProtocols =
|
||||
(_sslProtocols == SslProtocols.None) ? SecurityProtocol.DefaultSecurityProtocols : _sslProtocols;
|
||||
|
||||
#pragma warning disable 0618 // SSL2/SSL3 are deprecated
|
||||
if ((sslProtocols & SslProtocols.Ssl2) != 0)
|
||||
{
|
||||
optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_SSL2;
|
||||
}
|
||||
|
||||
if ((sslProtocols & SslProtocols.Ssl3) != 0)
|
||||
{
|
||||
optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_SSL3;
|
||||
}
|
||||
#pragma warning restore 0618
|
||||
|
||||
if ((sslProtocols & SslProtocols.Tls) != 0)
|
||||
{
|
||||
@ -947,7 +967,7 @@ namespace System.Net.Http
|
||||
(int)_sendTimeout.TotalMilliseconds,
|
||||
(int)_receiveHeadersTimeout.TotalMilliseconds))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetTimeouts));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1204,7 +1224,7 @@ namespace System.Net.Http
|
||||
option,
|
||||
ref optionData))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetOption));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1217,7 +1237,7 @@ namespace System.Net.Http
|
||||
optionData,
|
||||
(uint)optionData.Length))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetOption));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1234,7 +1254,7 @@ namespace System.Net.Http
|
||||
optionData,
|
||||
optionSize))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSetOption));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1304,18 +1324,18 @@ namespace System.Net.Http
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (lastError != Interop.WinHttp.ERROR_INVALID_HANDLE) // Ignore error if handle was already closed.
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpSetStatusCallback));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ThrowOnInvalidHandle(SafeWinHttpHandle handle)
|
||||
private void ThrowOnInvalidHandle(SafeWinHttpHandle handle, string nameOfCalledFunction)
|
||||
{
|
||||
if (handle.IsInvalid)
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
WinHttpTraceHelper.Trace("WinHttpHandler.ThrowOnInvalidHandle: error={0}", lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameOfCalledFunction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1333,11 +1353,13 @@ namespace System.Net.Http
|
||||
0,
|
||||
state.ToIntPtr()))
|
||||
{
|
||||
// Dispose (which will unpin) the state object. Since this failed, WinHTTP won't associate
|
||||
// our context value (state object) to the request handle. And thus we won't get HANDLE_CLOSING
|
||||
// notifications which would normally cause the state object to be unpinned and disposed.
|
||||
// WinHTTP doesn't always associate our context value (state object) to the request handle.
|
||||
// And thus we might not get a HANDLE_CLOSING notification which would normally cause the
|
||||
// state object to be unpinned and disposed. So, we manually dispose the request handle and
|
||||
// state object here.
|
||||
state.RequestHandle.Dispose();
|
||||
state.Dispose();
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpSendRequest));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1361,7 +1383,7 @@ namespace System.Net.Http
|
||||
{
|
||||
if (!Interop.WinHttp.WinHttpReceiveResponse(state.RequestHandle, IntPtr.Zero))
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingLastError();
|
||||
throw WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpReceiveResponse));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,8 +110,19 @@ namespace System.Net.Http
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Interop.WinHttp.WinHttpCloseHandle(handle);
|
||||
state.SavedException = ex;
|
||||
if (state.RequestHandle != null)
|
||||
{
|
||||
// Since we got a fatal error processing the request callback,
|
||||
// we need to close the WinHttp request handle in order to
|
||||
// abort the currently executing WinHttp async operation.
|
||||
//
|
||||
// We must always call Dispose() against the SafeWinHttpHandle
|
||||
// wrapper and never close directly the raw WinHttp handle.
|
||||
// The SafeWinHttpHandle wrapper is thread-safe and guarantees
|
||||
// calling the underlying WinHttpCloseHandle() function only once.
|
||||
state.RequestHandle.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +225,10 @@ namespace System.Net.Http
|
||||
{
|
||||
state.ServerCredentials = null;
|
||||
}
|
||||
|
||||
// Similarly, we need to clear any Auth headers that were added to the request manually or
|
||||
// through the default headers.
|
||||
ResetAuthRequestHeaders(state);
|
||||
}
|
||||
|
||||
private static void OnRequestSendingRequest(WinHttpRequestState state)
|
||||
@ -256,7 +271,7 @@ namespace System.Net.Http
|
||||
return;
|
||||
}
|
||||
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, "WINHTTP_CALLBACK_STATUS_SENDING_REQUEST/WinHttpQueryOption");
|
||||
}
|
||||
|
||||
// Get any additional certificates sent from the remote server during the TLS/SSL handshake.
|
||||
@ -291,7 +306,7 @@ namespace System.Net.Http
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(
|
||||
(int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE, ex);
|
||||
(int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE, "X509Chain.Build", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -306,7 +321,7 @@ namespace System.Net.Http
|
||||
if (!result)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(
|
||||
(int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);
|
||||
(int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE, "ServerCertificateValidationCallback");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,7 +332,7 @@ namespace System.Net.Http
|
||||
|
||||
Debug.Assert(state != null, "OnRequestError: state is null");
|
||||
|
||||
Exception innerException = WinHttpException.CreateExceptionUsingError(unchecked((int)asyncResult.dwError));
|
||||
Exception innerException = WinHttpException.CreateExceptionUsingError(unchecked((int)asyncResult.dwError), "WINHTTP_CALLBACK_STATUS_REQUEST_ERROR");
|
||||
|
||||
switch (unchecked((uint)asyncResult.dwResult.ToInt32()))
|
||||
{
|
||||
@ -404,5 +419,25 @@ namespace System.Net.Http
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetAuthRequestHeaders(WinHttpRequestState state)
|
||||
{
|
||||
const string AuthHeaderNameWithColon = "Authorization:";
|
||||
SafeWinHttpHandle requestHandle = state.RequestHandle;
|
||||
|
||||
// Clear auth headers.
|
||||
if (!Interop.WinHttp.WinHttpAddRequestHeaders(
|
||||
requestHandle,
|
||||
AuthHeaderNameWithColon,
|
||||
(uint)AuthHeaderNameWithColon.Length,
|
||||
Interop.WinHttp.WINHTTP_ADDREQ_FLAG_REPLACE))
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, "WINHTTP_CALLBACK_STATUS_REDIRECT/WinHttpAddRequestHeaders");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ namespace System.Net.Http
|
||||
IntPtr.Zero))
|
||||
{
|
||||
_state.TcsInternalWriteDataToRequestStream.TrySetException(
|
||||
new IOException(SR.net_http_io_write, WinHttpException.CreateExceptionUsingLastError()));
|
||||
new IOException(SR.net_http_io_write, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpWriteData))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ namespace System.Net.Http
|
||||
}
|
||||
}
|
||||
|
||||
response.Content = new NoWriteNoSeekStreamContent(decompressedStream, state.CancellationToken);
|
||||
response.Content = new NoWriteNoSeekStreamContent(decompressedStream);
|
||||
response.RequestMessage = request;
|
||||
|
||||
// Parse raw response headers and place them into response message.
|
||||
@ -127,7 +127,7 @@ namespace System.Net.Http
|
||||
ref resultSize,
|
||||
IntPtr.Zero))
|
||||
{
|
||||
WinHttpException.ThrowExceptionUsingLastError();
|
||||
WinHttpException.ThrowExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpQueryHeaders));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -189,7 +189,7 @@ namespace System.Net.Http
|
||||
return GetResponseHeader(requestHandle, infoLevel, ref buffer, ref index, out headerValue);
|
||||
}
|
||||
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -216,7 +216,7 @@ namespace System.Net.Http
|
||||
|
||||
Debug.Assert(lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER, "buffer must be of sufficient size.");
|
||||
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ namespace System.Net.Http
|
||||
|
||||
if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError);
|
||||
throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ namespace System.Net.Http
|
||||
{
|
||||
if (!Interop.WinHttp.WinHttpQueryDataAvailable(_requestHandle, IntPtr.Zero))
|
||||
{
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError());
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpQueryDataAvailable)));
|
||||
}
|
||||
}
|
||||
int bytesAvailable = await _state.LifecycleAwaitable;
|
||||
@ -137,7 +137,7 @@ namespace System.Net.Http
|
||||
{
|
||||
if (!Interop.WinHttp.WinHttpReadData(_requestHandle, Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0), (uint)Math.Min(bytesAvailable, buffer.Length), IntPtr.Zero))
|
||||
{
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError());
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpReadData)));
|
||||
}
|
||||
}
|
||||
int bytesRead = await _state.LifecycleAwaitable;
|
||||
@ -222,7 +222,7 @@ namespace System.Net.Http
|
||||
Debug.Assert(!_requestHandle.IsInvalid);
|
||||
if (!Interop.WinHttp.WinHttpQueryDataAvailable(_requestHandle, IntPtr.Zero))
|
||||
{
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError());
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpQueryDataAvailable)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ namespace System.Net.Http
|
||||
(uint)Math.Min(bytesAvailable, count),
|
||||
IntPtr.Zero))
|
||||
{
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError());
|
||||
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpReadData)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,14 +138,14 @@ namespace System.Net.Http
|
||||
|
||||
uint apiIndex = (uint)asyncResult.dwResult.ToInt32();
|
||||
uint error = asyncResult.dwError;
|
||||
|
||||
string apiName = GetNameFromApiIndex(apiIndex);
|
||||
WriteLine(
|
||||
"{0}: api={1}, error={2}({3}) \"{4}\"",
|
||||
message,
|
||||
GetNameFromApiIndex(apiIndex),
|
||||
apiName,
|
||||
GetNameFromError(error),
|
||||
error,
|
||||
WinHttpException.GetErrorMessage((int)error));
|
||||
WinHttpException.GetErrorMessage((int)error, apiName));
|
||||
}
|
||||
|
||||
private static void WriteLine(string message)
|
||||
|
@ -14,6 +14,9 @@ namespace System.Net.Http
|
||||
internal class WinInetProxyHelper
|
||||
{
|
||||
private bool _useProxy = false;
|
||||
private bool _autoDetectionFailed;
|
||||
private int _lastTimeAutoDetectionFailed; // Environment.TickCount units (milliseconds).
|
||||
private const int _recentAutoDetectionInterval = 120_000; // 2 minutes in milliseconds.
|
||||
|
||||
public WinInetProxyHelper()
|
||||
{
|
||||
@ -79,6 +82,10 @@ namespace System.Net.Http
|
||||
|
||||
public string ProxyBypass { get; set; }
|
||||
|
||||
public bool RecentAutoDetectionFailure =>
|
||||
_autoDetectionFailed &&
|
||||
Environment.TickCount - _lastTimeAutoDetectionFailed <= _recentAutoDetectionInterval;
|
||||
|
||||
public bool GetProxyForUrl(
|
||||
SafeWinHttpHandle sessionHandle,
|
||||
Uri uri,
|
||||
@ -123,6 +130,7 @@ namespace System.Net.Http
|
||||
var repeat = false;
|
||||
do
|
||||
{
|
||||
_autoDetectionFailed = false;
|
||||
if (Interop.WinHttp.WinHttpGetProxyForUrl(
|
||||
sessionHandle,
|
||||
uri.AbsoluteUri,
|
||||
@ -131,7 +139,7 @@ namespace System.Net.Http
|
||||
{
|
||||
WinHttpTraceHelper.Trace("WinInetProxyHelper.GetProxyForUrl: Using autoconfig proxy settings");
|
||||
useProxy = true;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -154,6 +162,12 @@ namespace System.Net.Http
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastError == Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED)
|
||||
{
|
||||
_autoDetectionFailed = true;
|
||||
_lastTimeAutoDetectionFailed = Environment.TickCount;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ using Xunit.Abstractions;
|
||||
// WinHttpHandler is a class and not a namespace and can't be part of namespace paths.
|
||||
namespace System.Net.Http.WinHttpHandlerFunctional.Tests
|
||||
{
|
||||
using Configuration = System.Net.Test.Common.Configuration;
|
||||
|
||||
// Note: Disposing the HttpClient object automatically disposes the handler within. So, it is not necessary
|
||||
// to separately Dispose (or have a 'using' statement) for the handler.
|
||||
[SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "WinHttpHandler not supported on UAP")]
|
||||
@ -113,6 +115,25 @@ namespace System.Net.Http.WinHttpHandlerFunctional.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendAsync_GetUsingChunkedEncoding_ThrowsHttpRequestException()
|
||||
{
|
||||
// WinHTTP doesn't support GET requests with a request body that uses
|
||||
// chunked encoding. This test pins this behavior and verifies that the
|
||||
// error handling is working correctly.
|
||||
var server = new Uri("http://www.microsoft.com"); // No network I/O actually happens.
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, server);
|
||||
request.Content = new StringContent("Request body");
|
||||
request.Headers.TransferEncodingChunked = true;
|
||||
|
||||
var handler = new WinHttpHandler();
|
||||
using (HttpClient client = new HttpClient(handler))
|
||||
{
|
||||
HttpRequestException ex = await Assert.ThrowsAsync<HttpRequestException>(() => client.SendAsync(request));
|
||||
_output.WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static bool JsonMessageContainsKeyValue(string message, string key, string value)
|
||||
{
|
||||
// TODO: Merge with System.Net.Http TestHelper class as part of GitHub Issue #4989.
|
||||
|
@ -73,9 +73,6 @@
|
||||
<Compile Include="$(CommonPath)\System\Net\Http\NoWriteNoSeekStreamContent.cs">
|
||||
<Link>Common\System\Net\Http\NoWriteNoSeekStreamContent.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Net\Http\WinHttpException.cs">
|
||||
<Link>Common\System\Net\Http\WinHttpException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Net\Security\CertificateHelper.cs">
|
||||
<Link>Common\System\Net\Security\CertificateHelper.cs</Link>
|
||||
</Compile>
|
||||
@ -103,6 +100,9 @@
|
||||
<Compile Include="..\..\src\System\Net\Http\WinHttpCookieContainerAdapter.cs">
|
||||
<Link>ProductionCode\WinHttpCookieContainerAdapter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\src\System\Net\Http\WinHttpException.cs">
|
||||
<Link>ProductionCode\WinHttpException.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\src\System\Net\Http\WinHttpHandler.cs">
|
||||
<Link>ProductionCode\WinHttpHandler.cs</Link>
|
||||
</Compile>
|
||||
|
@ -435,15 +435,6 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
|
||||
handler.ReceiveHeadersTimeout = Timeout.InfiniteTimeSpan;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SslProtocolSupport.UnsupportedSslProtocolsTestData))]
|
||||
public void SslProtocols_SetUsingUnsupported_Throws(SslProtocols protocol)
|
||||
{
|
||||
var handler = new WinHttpHandler();
|
||||
|
||||
Assert.Throws<NotSupportedException>(() => { handler.SslProtocols = protocol; });
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[ClassData(typeof(SslProtocolSupport.SupportedSslProtocolsTestData))]
|
||||
public void SslProtocols_SetUsingSupported_Success(SslProtocols protocol)
|
||||
@ -460,33 +451,27 @@ namespace System.Net.Http.WinHttpHandlerUnitTests
|
||||
handler.SslProtocols = SslProtocols.None;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SslProtocols_SetUsingInvalidEnum_Throws()
|
||||
{
|
||||
var handler = new WinHttpHandler();
|
||||
|
||||
Assert.Throws<NotSupportedException>(() => { handler.SslProtocols = (SslProtocols)4096; });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SslProtocols_SetUsingValidEnums_ExpectedWinHttpHandleSettings()
|
||||
[Theory]
|
||||
[InlineData(
|
||||
SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12,
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2)]
|
||||
#pragma warning disable 0618
|
||||
[InlineData(
|
||||
SslProtocols.Ssl2 | SslProtocols.Ssl3,
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 |
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_SSL3)]
|
||||
#pragma warning restore 0618
|
||||
public void SslProtocols_SetUsingValidEnums_ExpectedWinHttpHandleSettings(
|
||||
SslProtocols specified, uint expectedProtocols)
|
||||
{
|
||||
var handler = new WinHttpHandler();
|
||||
|
||||
SendRequestHelper.Send(
|
||||
handler,
|
||||
delegate
|
||||
{
|
||||
handler.SslProtocols =
|
||||
SslProtocols.Tls |
|
||||
SslProtocols.Tls11 |
|
||||
SslProtocols.Tls12;
|
||||
});
|
||||
delegate { handler.SslProtocols = specified; });
|
||||
|
||||
uint expectedProtocols =
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
|
||||
Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
|
||||
Assert.Equal(expectedProtocols, APICallHistory.WinHttpOptionSecureProtocols);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user