090d471348bff608ca32d1a46d35ae00dee8d5b5
[platform/upstream/dotnet/runtime.git] /
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.
4
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Net.Test.Common;
8 using System.Runtime.InteropServices;
9 using System.Text;
10 using System.Threading.Tasks;
11 using Microsoft.DotNet.RemoteExecutor;
12 using Xunit;
13 using Xunit.Abstractions;
14
15 namespace System.Net.Http.Functional.Tests
16 {
17     using Configuration = System.Net.Test.Common.Configuration;
18
19     public abstract class HttpClientHandler_DefaultProxyCredentials_Test : HttpClientHandlerTestBase
20     {
21         public HttpClientHandler_DefaultProxyCredentials_Test(ITestOutputHelper output) : base(output) { }
22
23         [Fact]
24         public void Default_Get_Null()
25         {
26             using (HttpClientHandler handler = CreateHttpClientHandler())
27             {
28                 Assert.Null(handler.DefaultProxyCredentials);
29             }
30         }
31
32         [Fact]
33         public void SetGet_Roundtrips()
34         {
35             using (HttpClientHandler handler = CreateHttpClientHandler())
36             {
37                 var creds = new NetworkCredential("username", "password", "domain");
38
39                 handler.DefaultProxyCredentials = null;
40                 Assert.Null(handler.DefaultProxyCredentials);
41
42                 handler.DefaultProxyCredentials = creds;
43                 Assert.Same(creds, handler.DefaultProxyCredentials);
44
45                 handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
46                 Assert.Same(CredentialCache.DefaultCredentials, handler.DefaultProxyCredentials);
47             }
48         }
49
50         [Fact]
51         public async Task ProxyExplicitlyProvided_DefaultCredentials_Ignored()
52         {
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}"));
56
57             await LoopbackServer.CreateClientAndServerAsync(async proxyUrl =>
58             {
59                 using (HttpClientHandler handler = CreateHttpClientHandler())
60                 using (HttpClient client = CreateHttpClient(handler))
61                 {
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
65                     {
66                         Assert.Equal(HttpStatusCode.OK, response.StatusCode);
67                     }
68                 }
69             }, async server =>
70             {
71                 await server.AcceptConnectionSendResponseAndCloseAsync(
72                     HttpStatusCode.ProxyAuthenticationRequired, "Proxy-Authenticate: Basic\r\n");
73
74                 List<string> headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.OK);
75                 Assert.Equal(expectCreds, LoopbackServer.GetRequestHeaderValue(headers, "Proxy-Authorization"));
76             });
77         }
78
79         [ActiveIssue("https://github.com/dotnet/corefx/issues/42323")]
80         [OuterLoop("Uses external server")]
81         [PlatformSpecific(TestPlatforms.AnyUnix)] // The default proxy is resolved via WinINet on Windows.
82         [Theory]
83         [InlineData(false)]
84         [InlineData(true)]
85         public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy)
86         {
87             const string ExpectedUsername = "rightusername";
88             const string ExpectedPassword = "rightpassword";
89             LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword };
90
91             await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUri) =>
92             {
93                 // SocketsHttpHandler can read a default proxy from the http_proxy environment variable.  Ensure that when it does,
94                 // our default proxy credentials are used.  To avoid messing up anything else in this process, we run the
95                 // test in another process.
96                 var psi = new ProcessStartInfo();
97                 Task<List<string>> proxyTask = null;
98
99                 if (useProxy)
100                 {
101                     proxyTask = proxyServer.AcceptConnectionPerformAuthenticationAndCloseAsync("Proxy-Authenticate: Basic realm=\"NetCore\"\r\n");
102                     psi.Environment.Add("http_proxy", $"http://{proxyUri.Host}:{proxyUri.Port}");
103                 }
104
105                 RemoteExecutor.Invoke(async (useProxyString, useHttp2String) =>
106                 {
107                     using (HttpClientHandler handler = CreateHttpClientHandler(useHttp2String))
108                     using (HttpClient client = CreateHttpClient(handler, useHttp2String))
109                     {
110                         var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword);
111                         handler.DefaultProxyCredentials = creds;
112                         handler.UseProxy = bool.Parse(useProxyString);
113
114                         HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
115                         // Correctness of user and password is done in server part.
116                         Assert.True(response.StatusCode == HttpStatusCode.OK);
117                     }
118                 }, useProxy.ToString(), UseHttp2.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose();
119                 if (useProxy)
120                 {
121                     await proxyTask;
122                 }
123             }, options);
124         }
125
126         // The purpose of this test is mainly to validate the .NET Framework OOB System.Net.Http implementation
127         // since it has an underlying dependency to WebRequest. While .NET Core implementations of System.Net.Http
128         // are not using any WebRequest code, the test is still useful to validate correctness.
129         [OuterLoop("Uses external server")]
130         [Fact]
131         public async Task ProxyNotExplicitlyProvided_DefaultCredentialsSet_DefaultWebProxySetToNull_Success()
132         {
133             WebRequest.DefaultWebProxy = null;
134
135             using (HttpClientHandler handler = CreateHttpClientHandler())
136             using (HttpClient client = CreateHttpClient(handler))
137             {
138                 handler.DefaultProxyCredentials = new NetworkCredential("UsernameNotUsed", "PasswordNotUsed");
139                 HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer);
140
141                 Assert.Equal(HttpStatusCode.OK, response.StatusCode);
142             }
143         }
144     }
145 }