public void HttpClientUsesSslCertEnvironmentVariables() { // We set SSL_CERT_DIR and SSL_CERT_FILE to empty locations. // The HttpClient should fail to validate the server certificate. var psi = new ProcessStartInfo(); string sslCertDir = GetTestFilePath(); Directory.CreateDirectory(sslCertDir); psi.Environment.Add("SSL_CERT_DIR", sslCertDir); string sslCertFile = GetTestFilePath(); File.WriteAllText(sslCertFile, ""); psi.Environment.Add("SSL_CERT_FILE", sslCertFile); RemoteExecutor.Invoke(async(useVersionString, allowAllCertificatesString) => { const string Url = "https://www.microsoft.com"; var version = Version.Parse(useVersionString); using HttpClientHandler handler = CreateHttpClientHandler( useVersion: version, allowAllCertificates: version >= HttpVersion20.Value && bool.Parse(allowAllCertificatesString)); using HttpClient client = CreateHttpClient(handler, useVersionString); await Assert.ThrowsAsync <HttpRequestException>(() => client.GetAsync(Url)); }, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); }
public static string[] TranslateArray(string[] texts, string from, string to, string contentType) { string fromCode = string.Empty; string toCode = string.Empty; if (from.ToLower() == "Auto-Detect".ToLower() || from == string.Empty) { fromCode = string.Empty; } else { try { fromCode = AvailableLanguages.First(t => t.Value == from).Key; } catch { fromCode = from; } } toCode = LanguageNameToLanguageCode(to); if (useversion == UseVersion.V2) { return(TranslateArrayV2(texts, fromCode, toCode, contentType)); } else { string[] result = TranslateV3Async(texts, fromCode, toCode, _CategoryID, contentType).Result; if ((result == null) && IsCustomCategory(_CategoryID)) { useversion = UseVersion.V2; return(TranslateArrayV2(texts, fromCode, toCode, contentType)); } return(result); } }
/// <summary> /// Test if a given category value is a valid category in the system. /// Works across V2 and V3 of the API. /// </summary> /// <param name="category">Category ID</param> /// <returns>True if the category is valid</returns> public static bool IsCategoryValid(string category) { useversion = UseVersion.V3; if (category == "") { return(true); } if (category == string.Empty) { return(true); } if (category.ToLower() == "general") { return(true); } if (category.ToLower() == "generalnn") { return(true); } //Test V2 API and V3 API both bool testV2 = IsCategoryValidV2(category); if (testV2) { useversion = UseVersion.V2; return(true); } else { Task <bool> testV3 = IsCategoryValidV3Async(category); return(testV3.Result); } }
public async Task CancelPendingRequest_DropsStalledConnectionAttempt() { if (UseVersion == HttpVersion.Version30) { // HTTP3 does not support ConnectCallback return; } await CancelPendingRequest_DropsStalledConnectionAttempt_Impl(UseVersion.ToString()); }
public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy) { const string ExpectedUsername = "******"; const string ExpectedPassword = "******"; LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword }; await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUri) => { // SocketsHttpHandler can read a default proxy from the http_proxy environment variable. Ensure that when it does, // our default proxy credentials are used. To avoid messing up anything else in this process, we run the // test in another process. var psi = new ProcessStartInfo(); Task <List <string> > proxyTask = null; if (useProxy) { proxyTask = proxyServer.AcceptConnectionPerformAuthenticationAndCloseAsync("Proxy-Authenticate: Basic realm=\"NetCore\"\r\n"); psi.Environment.Add("http_proxy", $"http://{proxyUri.Host}:{proxyUri.Port}"); } RemoteExecutor.Invoke(async(useProxyString, useVersionString) => { using (HttpClientHandler handler = CreateHttpClientHandler(useVersionString)) using (HttpClient client = CreateHttpClient(handler, useVersionString)) { var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword); handler.DefaultProxyCredentials = creds; handler.UseProxy = bool.Parse(useProxyString); HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer); // Correctness of user and password is done in server part. Assert.True(response.StatusCode == HttpStatusCode.OK); } }, useProxy.ToString(), UseVersion.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); if (useProxy) { await proxyTask; } }, options); }
public void Proxy_UseEnvironmentVariableToSetSystemProxy_RequestGoesThruProxy() { RemoteExecutor.Invoke(async(useVersionString) => { var options = new LoopbackProxyServer.Options { AddViaRequestHeader = true }; using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create(options)) { Environment.SetEnvironmentVariable("http_proxy", proxyServer.Uri.AbsoluteUri.ToString()); using (HttpClient client = CreateHttpClient(useVersionString)) using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.RemoteEchoServer)) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); string body = await response.Content.ReadAsStringAsync(); Assert.Contains(proxyServer.ViaHeader, body); } } }, UseVersion.ToString()).Dispose(); }
public async Task UseCallback_BadCertificate_ExpectedPolicyErrors(string url, SslPolicyErrors expectedErrors) { const int SEC_E_BUFFER_TOO_SMALL = unchecked ((int)0x80090321); if (!ClientSupportsDHECipherSuites) { return; } try { await UseCallback_BadCertificate_ExpectedPolicyErrors_Helper(url, UseVersion.ToString(), expectedErrors); } catch (HttpRequestException e) when(e.InnerException?.GetType().Name == "WinHttpException" && e.InnerException.HResult == SEC_E_BUFFER_TOO_SMALL && !PlatformDetection.IsWindows10Version1607OrGreater) { // Testing on old Windows versions can hit https://github.com/dotnet/runtime/issues/17005 // Ignore SEC_E_BUFFER_TOO_SMALL error on such cases. } }
/// <summary> /// Translates an array of strings from the from langauge code to the to language code. /// From langauge code can stay empty, in that case the source language is auto-detected, across all elements of the array together. /// </summary> /// <param name="texts">Array of strings to translate</param> /// <param name="from">From language code. May be empty</param> /// <param name="to">To language code. Must be a valid language</param> /// <param name="contentType">text/plan or text/html depending on the type of string</param> /// <returns></returns> public static string[] TranslateArray(string[] texts, string from, string to, string contentType = "text/plain") { string fromCode = string.Empty; string toCode = string.Empty; if (autoDetectStrings.Contains(from.ToLower(CultureInfo.InvariantCulture)) || from == string.Empty) { fromCode = string.Empty; } else { try { fromCode = AvailableLanguages.First(t => t.Value == from).Key; } catch { fromCode = from; } } toCode = LanguageNameToLanguageCode(to); if (useversion == UseVersion.unknown) { IsCategoryValid(_CategoryID); } if (useversion == UseVersion.V2) { return(TranslateArrayV2(texts, fromCode, toCode, contentType)); } else { string[] result = TranslateV3Async(texts, fromCode, toCode, _CategoryID, contentType).Result; if ((result == null) && IsCustomCategory(_CategoryID)) { useversion = UseVersion.V2; return(TranslateArrayV2(texts, fromCode, toCode, contentType)); } return(result); } }
public void EventSource_SuccessfulRequest_LogsStartStop(string testMethod) { if (UseVersion.Major != 1 && !testMethod.EndsWith("Async")) { // Synchronous requests are only supported for HTTP/1.1 return; } RemoteExecutor.Invoke(async(useVersionString, testMethod) => { const int ResponseContentLength = 42; Version version = Version.Parse(useVersionString); using var listener = new TestEventListener("System.Net.Http", EventLevel.Verbose, eventCounterInterval: 0.1d); listener.AddActivityTracking(); bool buffersResponse = false; var events = new ConcurrentQueue <(EventWrittenEventArgs Event, Guid ActivityId)>(); await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), async() => { await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { using HttpClientHandler handler = CreateHttpClientHandler(useVersionString); using HttpClient client = CreateHttpClient(handler, useVersionString); using var invoker = new HttpMessageInvoker(handler); var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = version }; switch (testMethod) { case "GetAsync": { buffersResponse = true; await client.GetAsync(uri); } break; case "Send": { buffersResponse = true; await Task.Run(() => client.Send(request)); } break; case "UnbufferedSend": { buffersResponse = false; HttpResponseMessage response = await Task.Run(() => client.Send(request, HttpCompletionOption.ResponseHeadersRead)); response.Content.CopyTo(Stream.Null, null, default); } break; case "SendAsync": { buffersResponse = true; await client.SendAsync(request); } break; case "UnbufferedSendAsync": { buffersResponse = false; HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); await response.Content.CopyToAsync(Stream.Null); } break; case "GetStringAsync": { buffersResponse = true; await client.GetStringAsync(uri); } break; case "GetByteArrayAsync": { buffersResponse = true; await client.GetByteArrayAsync(uri); } break; case "GetStreamAsync": { buffersResponse = false; Stream responseStream = await client.GetStreamAsync(uri); await responseStream.CopyToAsync(Stream.Null); } break; case "InvokerSend": { buffersResponse = false; HttpResponseMessage response = await Task.Run(() => invoker.Send(request, cancellationToken: default)); await response.Content.CopyToAsync(Stream.Null); } break; case "InvokerSendAsync": { buffersResponse = false; HttpResponseMessage response = await invoker.SendAsync(request, cancellationToken: default); await response.Content.CopyToAsync(Stream.Null); } break; } }, async server => { await server.AcceptConnectionAsync(async connection => { await WaitForEventCountersAsync(events); await connection.ReadRequestDataAsync(); await connection.SendResponseAsync(content: new string('a', ResponseContentLength)); }); }); await WaitForEventCountersAsync(events); }); Assert.DoesNotContain(events, e => e.Event.EventId == 0); // errors from the EventSource itself ValidateStartFailedStopEvents(events); ValidateConnectionEstablishedClosed(events, version); ValidateRequestResponseStartStopEvents( events, requestContentLength: null, responseContentLength: buffersResponse ? ResponseContentLength : null, count: 1); ValidateEventCounters(events, requestCount: 1, shouldHaveFailures: false); }, UseVersion.ToString(), testMethod).Dispose(); }
public void EventSource_UnsuccessfulRequest_LogsStartFailedStop(string testMethod) { if (UseVersion.Major != 1 && !testMethod.EndsWith("Async")) { // Synchronous requests are only supported for HTTP/1.1 return; } RemoteExecutor.Invoke(async(useVersionString, testMethod) => { Version version = Version.Parse(useVersionString); using var listener = new TestEventListener("System.Net.Http", EventLevel.Verbose, eventCounterInterval: 0.1d); listener.AddActivityTracking(); var events = new ConcurrentQueue <(EventWrittenEventArgs Event, Guid ActivityId)>(); await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), async() => { var semaphore = new SemaphoreSlim(0, 1); var cts = new CancellationTokenSource(); await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { using HttpClientHandler handler = CreateHttpClientHandler(useVersionString); using HttpClient client = CreateHttpClient(handler, useVersionString); using var invoker = new HttpMessageInvoker(handler); var request = new HttpRequestMessage(HttpMethod.Get, uri) { Version = version }; switch (testMethod) { case "GetAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.GetAsync(uri, cts.Token)); break; case "Send": await Assert.ThrowsAsync <TaskCanceledException>(async() => await Task.Run(() => client.Send(request, cts.Token))); break; case "UnbufferedSend": await Assert.ThrowsAsync <TaskCanceledException>(async() => await Task.Run(() => client.Send(request, HttpCompletionOption.ResponseHeadersRead, cts.Token))); break; case "SendAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.SendAsync(request, cts.Token)); break; case "UnbufferedSendAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cts.Token)); break; case "GetStringAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.GetStringAsync(uri, cts.Token)); break; case "GetByteArrayAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.GetByteArrayAsync(uri, cts.Token)); break; case "GetStreamAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await client.GetStreamAsync(uri, cts.Token)); break; case "InvokerSend": await Assert.ThrowsAsync <TaskCanceledException>(async() => await Task.Run(() => invoker.Send(request, cts.Token))); break; case "InvokerSendAsync": await Assert.ThrowsAsync <TaskCanceledException>(async() => await invoker.SendAsync(request, cts.Token)); break; } semaphore.Release(); }, async server => { await server.AcceptConnectionAsync(async connection => { await WaitForEventCountersAsync(events); cts.Cancel(); Assert.True(await semaphore.WaitAsync(TimeSpan.FromSeconds(30))); connection.Dispose(); }); }); await WaitForEventCountersAsync(events); }); Assert.DoesNotContain(events, e => e.Event.EventId == 0); // errors from the EventSource itself ValidateStartFailedStopEvents(events, shouldHaveFailures: true); ValidateConnectionEstablishedClosed(events, version); ValidateEventCounters(events, requestCount: 1, shouldHaveFailures: true); }, UseVersion.ToString(), testMethod).Dispose(); }
public void CancelPendingRequest_DropsStalledConnectionAttempt_CustomPendingConnectionTimeout() { if (UseVersion == HttpVersion.Version30) { // HTTP3 does not support ConnectCallback return; } RemoteInvokeOptions options = new RemoteInvokeOptions(); options.StartInfo.EnvironmentVariables["DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_PENDINGCONNECTIONTIMEOUTONREQUESTCOMPLETION"] = "42"; RemoteExecutor.Invoke(CancelPendingRequest_DropsStalledConnectionAttempt_Impl, UseVersion.ToString(), options).Dispose(); }
public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(bool useProxy) { const string ExpectedUsername = "******"; const string ExpectedPassword = "******"; LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword }; await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() => { var psi = new ProcessStartInfo(); psi.Environment.Add("http_proxy", $"http://{uri.Host}:{uri.Port}"); RemoteExecutor.Invoke(async(useProxyString, useVersionString, uriString) => { using (HttpClientHandler handler = CreateHttpClientHandler(useVersionString)) using (HttpClient client = CreateHttpClient(handler, useVersionString)) { var creds = new NetworkCredential(ExpectedUsername, ExpectedPassword); handler.DefaultProxyCredentials = creds; handler.UseProxy = bool.Parse(useProxyString); HttpResponseMessage response = await client.GetAsync(uriString); // Correctness of user and password is done in server part. Assert.True(response.StatusCode == HttpStatusCode.OK); }; }, useProxy.ToString(), UseVersion.ToString(), // If proxy is used , the url does not matter. We set it to be different to avoid confusion. useProxy ? Configuration.Http.RemoteEchoServer.ToString() : uri.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); }), server => server.AcceptConnectionAsync(async connection => { const string headerName = "Proxy-Authorization"; List <string> lines = await connection.ReadRequestHeaderAsync().ConfigureAwait(false); // First request should not have proxy credentials in either case. for (int i = 1; i < lines.Count; i++) { Assert.False(lines[i].StartsWith(headerName)); } if (useProxy) { // Reject request and wait for authenticated one. await connection.SendResponseAsync(HttpStatusCode.ProxyAuthenticationRequired, "Proxy-Authenticate: Basic realm=\"NetCore\"\r\n").ConfigureAwait(false); lines = await connection.ReadRequestHeaderAsync().ConfigureAwait(false); bool valid = false; for (int i = 1; i < lines.Count; i++) { if (lines[i].StartsWith(headerName)) { valid = LoopbackServer.IsBasicAuthTokenValid(lines[i], options); } } Assert.True(valid); } await connection.SendResponseAsync(HttpStatusCode.OK).ConfigureAwait(false); })); }
protected override void Execute(CodeActivityContext context) { console = context.GetExtension <ActivityConsole>(); if (console == null) { console = new ActivityConsole(); } int version = UseVersion.Get(context); if (UseVersion2x.Get(context)) { UseVersion.Set(context, 2); } string platformKey = "InstallPath"; string keyName = string.Format(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\{0}", version); string msdeployExePath = (string)Microsoft.Win32.Registry.GetValue(keyName, platformKey, ""); if (string.IsNullOrEmpty(msdeployExePath)) { throw new ArgumentException(string.Format("Could not find msdeploy.exe for version '{0}'.", version)); } msdeployExePath = string.Format("\"{0}\"", System.IO.Path.Combine(msdeployExePath, "msdeploy.exe")); if (version == 2 && string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSDeployPath"))) { Environment.SetEnvironmentVariable("MSDeployPath", msdeployExePath); } string executablePath; string arguments; if (ExecutionType.Get(context) == MSDeployExecutionType.Exe) { executablePath = msdeployExePath; arguments = GetExeFileCommandLineArguments(context); } else { executablePath = CmdFileName.Get(context); arguments = GetCmdFileCommandLineArguments(context); } string output = string.Empty; CommandLine commandLineHelper = new CommandLine(); commandLineHelper.ReportProgress += new EventHandler <CommandLineProgressEventArgs>(commandLineHelper_ReportProgress); console.WriteLine(string.Format("{0} {1}\r\n", executablePath, arguments)); int returnValue = commandLineHelper.Execute(executablePath, arguments, out output); if (output.Contains("All arguments must begin with \"-\"") && ExecutionType.Get(context) == MSDeployExecutionType.Cmd && !string.IsNullOrEmpty(IISWebApplication.Get(context))) { console.WriteLine("\n"); console.WriteLine("**********************************************************************************************************************************************\n"); console.WriteLine("There is a bug with 2012 versions of the .cmd files generated, which does not allow '=' to be passed on the command line. Try the Exe method.\n"); console.WriteLine("**********************************************************************************************************************************************\n\n"); } if (output.Contains("Attempted to perform an unauthorized operation.") || output.Contains("ERROR_USER_UNAUTHORIZED") || output.Contains("ERROR_INSUFFICIENT_ACCESS_TO_SITE_FOLDER")) { console.WriteLine("\n"); console.WriteLine("***********************************************************************************************************************\n"); console.WriteLine("It seems the user account is not allowed to do this. Try running as administrator or specifying username and password.\n"); console.WriteLine("***********************************************************************************************************************\n\n"); } if (output.Contains("ERROR_CERTIFICATE_VALIDATION_FAILED")) { console.WriteLine("\n"); console.WriteLine("**********************************************************************************************************\n"); console.WriteLine("The SSL certificate is self signed and untrusted. Tick the 'Allow Untrusted Connection' box and try again. \n"); console.WriteLine("**********************************************************************************************************\n\n"); } if (returnValue != 0 || (!output.Contains("Total changes:"))) { throw new InvalidOperationException(output); } }