1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Net.Test.Common;
8 using System.Runtime.InteropServices;
10 using System.Threading.Tasks;
11 using Microsoft.DotNet.RemoteExecutor;
13 using Xunit.Abstractions;
15 namespace System.Net.Http.Functional.Tests
17 using Configuration = System.Net.Test.Common.Configuration;
19 public abstract class HttpClientHandler_DefaultProxyCredentials_Test : HttpClientHandlerTestBase
21 public HttpClientHandler_DefaultProxyCredentials_Test(ITestOutputHelper output) : base(output) { }
24 public void Default_Get_Null()
26 using (HttpClientHandler handler = CreateHttpClientHandler())
28 Assert.Null(handler.DefaultProxyCredentials);
33 public void SetGet_Roundtrips()
35 using (HttpClientHandler handler = CreateHttpClientHandler())
37 var creds = new NetworkCredential("username", "password", "domain");
39 handler.DefaultProxyCredentials = null;
40 Assert.Null(handler.DefaultProxyCredentials);
42 handler.DefaultProxyCredentials = creds;
43 Assert.Same(creds, handler.DefaultProxyCredentials);
45 handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
46 Assert.Same(CredentialCache.DefaultCredentials, handler.DefaultProxyCredentials);
51 public async Task ProxyExplicitlyProvided_DefaultCredentials_Ignored()
53 var explicitProxyCreds = new NetworkCredential("rightusername", "rightpassword");
54 var defaultSystemProxyCreds = new NetworkCredential("wrongusername", "wrongpassword");
55 string expectCreds = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{explicitProxyCreds.UserName}:{explicitProxyCreds.Password}"));
57 await LoopbackServer.CreateClientAndServerAsync(async proxyUrl =>
59 using (HttpClientHandler handler = CreateHttpClientHandler())
60 using (HttpClient client = CreateHttpClient(handler))
62 handler.Proxy = new UseSpecifiedUriWebProxy(proxyUrl, explicitProxyCreds);
63 handler.DefaultProxyCredentials = defaultSystemProxyCreds;
64 using (HttpResponseMessage response = await client.GetAsync("http://notatrealserver.com/")) // URL does not matter
66 Assert.Equal(HttpStatusCode.OK, response.StatusCode);
71 if (!IsCurlHandler) // libcurl sends Basic auth preemptively when only basic creds are provided; other handlers wait for 407.
73 await server.AcceptConnectionSendResponseAndCloseAsync(
74 HttpStatusCode.ProxyAuthenticationRequired, "Proxy-Authenticate: Basic\r\n");
77 List<string> headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.OK);
78 Assert.Equal(expectCreds, LoopbackServer.GetRequestHeaderValue(headers, "Proxy-Authorization"));
82 [OuterLoop("Uses external server")]
83 [PlatformSpecific(TestPlatforms.AnyUnix)] // The default proxy is resolved via WinINet on Windows.
87 public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy)
89 const string ExpectedUsername = "rightusername";
90 const string ExpectedPassword = "rightpassword";
91 LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword };
93 await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUri) =>
95 // libcurl will read a default proxy from the http_proxy environment variable. Ensure that when it does,
96 // our default proxy credentials are used. To avoid messing up anything else in this process, we run the
97 // test in another process.
98 var psi = new ProcessStartInfo();
99 Task<List<string>> proxyTask = null;
103 proxyTask = proxyServer.AcceptConnectionPerformAuthenticationAndCloseAsync("Proxy-Authenticate: Basic realm=\"NetCore\"\r\n");
104 psi.Environment.Add("http_proxy", $"http://{proxyUri.Host}:{proxyUri.Port}");
107 RemoteExecutor.Invoke(async (useProxyString, useSocketsHttpHandlerString, useHttp2String) =>
109 using (HttpClientHandler handler = CreateHttpClientHandler(useSocketsHttpHandlerString, useHttp2String))
110 using (HttpClient client = CreateHttpClient(handler, useHttp2String))
112 var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword);
113 handler.DefaultProxyCredentials = creds;
114 handler.UseProxy = bool.Parse(useProxyString);
116 HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
117 // Correctness of user and password is done in server part.
118 Assert.True(response.StatusCode == HttpStatusCode.OK);
120 }, useProxy.ToString(), UseSocketsHttpHandler.ToString(), UseHttp2.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose();
128 // The purpose of this test is mainly to validate the .NET Framework OOB System.Net.Http implementation
129 // since it has an underlying dependency to WebRequest. While .NET Core implementations of System.Net.Http
130 // are not using any WebRequest code, the test is still useful to validate correctness.
131 [OuterLoop("Uses external server")]
133 public async Task ProxyNotExplicitlyProvided_DefaultCredentialsSet_DefaultWebProxySetToNull_Success()
135 WebRequest.DefaultWebProxy = null;
137 using (HttpClientHandler handler = CreateHttpClientHandler())
138 using (HttpClient client = CreateHttpClient(handler))
140 handler.DefaultProxyCredentials = new NetworkCredential("UsernameNotUsed", "PasswordNotUsed");
141 HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
143 Assert.Equal(HttpStatusCode.OK, response.StatusCode);