public async Task SetProtocols_AfterRequest_ThrowsException() { if (!BackendSupportsSslConfiguration) { return; } using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( server.AcceptConnectionSendResponseAndCloseAsync(), client.GetAsync(url)); }); Assert.Throws <InvalidOperationException>(() => handler.SslProtocols = SslProtocols.Tls12); } }
public async Task GetAsync_ReceiveSetCookieHeader_CookieRemoved() { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = CreateHttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <HttpRequestData> serverTask = server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", $"{s_cookieName}=; Expires=Sun, 06 Nov 1994 08:49:37 GMT") }, s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(0, collection.Count); } }); }
public async Task GetAsync_RequestVersion11_Success() { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = HttpVersion.Version11; Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = server.AcceptConnectionSendResponseAndCloseAsync(); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); var requestLines = await serverTask; Assert.Equal($"GET {url.PathAndQuery} HTTP/1.1", requestLines[0]); } }, new LoopbackServer.Options { StreamWrapper = GetStream }); }
public void SendAsync_HttpTracingEnabled_Succeeds() { RemoteInvoke(async() => { using (var listener = new TestEventListener("Microsoft-System-Net-Http", EventLevel.Verbose)) { var events = new ConcurrentQueue <EventWrittenEventArgs>(); await listener.RunWithCallbackAsync(events.Enqueue, async() => { // Exercise various code paths to get coverage of tracing using (var client = new HttpClient()) { // Do a get to a loopback server await LoopbackServer.CreateServerAsync(async(server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( LoopbackServer.ReadRequestAndSendResponseAsync(server), client.GetAsync(url)); }); // Do a post to a remote server byte[] expectedData = Enumerable.Range(0, 20000).Select(i => (byte)i).ToArray(); HttpContent content = new ByteArrayContent(expectedData); content.Headers.ContentMD5 = TestHelper.ComputeMD5Hash(expectedData); using (HttpResponseMessage response = await client.PostAsync(Configuration.Http.RemoteEchoServer, content)) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } }); // We don't validate receiving specific events, but rather that we do at least // receive some events, and that enabling tracing doesn't cause other failures // in processing. Assert.InRange(events.Count, 1, int.MaxValue); } return(SuccessExitCode); }).Dispose(); }
public async Task GetAsync_SetCookieContainerAndMultipleCookieHeaders_BothCookiesSent() { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = CreateHttpClient(handler)) { var requestMessage = new HttpRequestMessage(HttpMethod.Get, url) { Version = UseVersion }; requestMessage.Headers.Add("Cookie", "A=1"); requestMessage.Headers.Add("Cookie", "B=2"); Task <HttpResponseMessage> getResponseTask = client.SendAsync(TestAsync, requestMessage); Task <HttpRequestData> serverTask = server.HandleRequestAsync(); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); HttpRequestData requestData = await serverTask; string cookieHeaderValue = GetCookieValue(requestData); #if NETFRAMEWORK // On .NET Framework multiple Cookie header values are treated as any other header values and are // concatenated using ", " as the separator. The container cookie is concatenated to // one of these values using the "; " cookie separator. var separators = new string[] { "; ", ", " }; #else var separators = new string[] { "; " }; #endif var cookieValues = cookieHeaderValue.Split(separators, StringSplitOptions.None); Assert.Contains(s_expectedCookieHeaderValue, cookieValues); Assert.Contains("A=1", cookieValues); Assert.Contains("B=2", cookieValues); Assert.Equal(3, cookieValues.Count()); } }); }
public async Task GetAsync_SetCookieContainerAndCookieHeader_BothCookiesSent() { if (IsNetfxHandler) { // Netfx handler does not support custom cookie header return; } if (IsCurlHandler) { // Issue #26983 // CurlHandler ignores container cookies when custom Cookie header is set. return; } await LoopbackServer.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = new HttpClient(handler)) { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, url); requestMessage.Headers.Add("Cookie", s_customCookieHeaderValue); Task <HttpResponseMessage> getResponseTask = client.SendAsync(requestMessage); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); List <string> requestLines = await serverTask; Assert.Equal(1, requestLines.Count(s => s.StartsWith("Cookie: "))); var cookies = requestLines.Single(s => s.StartsWith("Cookie: ")).Substring(8).Split(new string[] { "; " }, StringSplitOptions.None); Assert.Contains(s_expectedCookieHeaderValue, cookies); Assert.Contains(s_customCookieHeaderValue, cookies); Assert.Equal(2, cookies.Count()); } }); }
public async Task GetAsync_NoSpecifiedProtocol_DefaultsToTls12() { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = SslProtocols.Tls12 }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( client.GetAsync(url), server.AcceptConnectionAsync(async connection => { Assert.Equal(SslProtocols.Tls12, Assert.IsType <SslStream>(connection.Stream).SslProtocol); await connection.ReadRequestHeaderAndSendResponseAsync(); })); }, options); } }
[PlatformSpecific(TestPlatforms.Windows)] // Curl has issues with trailing headers https://github.com/curl/curl/issues/1354 public async Task GetAsync_TrailingHeaders_Ignored(bool includeTrailerHeader) { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (var client = new HttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); await TestHelper.WhenAllCompletedOrAnyFailed( getResponseTask, server.AcceptConnectionSendCustomResponseAndCloseAsync( "HTTP/1.1 200 OK\r\n" + "Connection: close\r\n" + "Transfer-Encoding: chunked\r\n" + (includeTrailerHeader ? "Trailer: MyCoolTrailerHeader\r\n" : "") + "\r\n" + "4\r\n" + "data\r\n" + "0\r\n" + "MyCoolTrailerHeader: amazingtrailer\r\n" + "\r\n")); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); if (includeTrailerHeader) { Assert.Contains("MyCoolTrailerHeader", response.Headers.GetValues("Trailer")); } Assert.False(response.Headers.Contains("MyCoolTrailerHeader"), "Trailer should have been ignored"); string data = await response.Content.ReadAsStringAsync(); Assert.Contains("data", data); Assert.DoesNotContain("MyCoolTrailerHeader", data); Assert.DoesNotContain("amazingtrailer", data); } } }); }
public async Task GetAsync_DisallowTls10_AllowTls11_AllowTls12() { using (var handler = new HttpClientHandler() { SslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12, ServerCertificateCustomValidationCallback = LoopbackServer.AllowAllCertificates }) using (var client = new HttpClient(handler)) { if (BackendSupportsSslConfiguration) { LoopbackServer.Options options = new LoopbackServer.Options { UseSsl = true }; options.SslProtocols = SslProtocols.Tls; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( Assert.ThrowsAsync <IOException>(() => LoopbackServer.ReadRequestAndSendResponseAsync(server, options: options)), Assert.ThrowsAsync <HttpRequestException>(() => client.GetAsync(url))); }, options); foreach (var prot in new[] { SslProtocols.Tls11, SslProtocols.Tls12 }) { options.SslProtocols = prot; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( LoopbackServer.ReadRequestAndSendResponseAsync(server, options: options), client.GetAsync(url)); }, options); } } else { await Assert.ThrowsAnyAsync <NotSupportedException>(() => client.GetAsync($"http://{Guid.NewGuid().ToString()}/")); } } }
public async Task SetDelegate_ConnectionSucceeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol) { // Overriding flag for the same reason we skip tests on Catalina // On OSX 10.13-10.14 we can override this flag to enable the scenario requestOnlyThisProtocol |= PlatformDetection.IsOSX && acceptedProtocol == SslProtocols.Tls; using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; if (requestOnlyThisProtocol) { handler.SslProtocols = acceptedProtocol; } else { // Explicitly setting protocols clears implementation default // restrictions on minimum TLS/SSL version // We currently know that some platforms like Debian 10 OpenSSL // will by default block < TLS 1.2 #if !NETFRAMEWORK handler.SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; #else handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; #endif } var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( server.AcceptConnectionSendResponseAndCloseAsync(), client.GetAsync(url)); }, options); } }
public async Task GetAsync_ReceiveInvalidSetCookieHeader_ValidCookiesAdded() { if (IsNetfxHandler) { // NetfxHandler incorrectly only processes one valid cookie return; } await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = new HttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <HttpRequestData> serverTask = server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", "A=1; Path=/;Expires=asdfsadgads"), // invalid Expires new HttpHeaderData("Set-Cookie", "B=2; Path=/"), new HttpHeaderData("Set-Cookie", "C=3; Path=/") }, s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(2, collection.Count); // Convert to array so we can more easily process contents, since CookieCollection does not implement IEnumerable<Cookie> Cookie[] cookies = new Cookie[3]; collection.CopyTo(cookies, 0); Assert.Contains(cookies, c => c.Name == "B" && c.Value == "2"); Assert.Contains(cookies, c => c.Name == "C" && c.Value == "3"); } }); }
public async Task GetAsync_RequestVersion0X_ThrowsOr11(int minorVersion) { Type exceptionType = null; if (UseSocketsHttpHandler) { exceptionType = typeof(NotSupportedException); } else if (PlatformDetection.IsFullFramework) { exceptionType = typeof(ArgumentException); } await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = new Version(0, minorVersion); Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = server.AcceptConnectionSendResponseAndCloseAsync(); if (exceptionType == null) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); var requestLines = await serverTask; Assert.Equal($"GET {url.PathAndQuery} HTTP/1.1", requestLines[0]); } else { await Assert.ThrowsAsync(exceptionType, (() => TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask))); } } }, new LoopbackServer.Options { StreamWrapper = GetStream_ClientDisconnectOk }); }
public async Task HttpClientHandler_MultipleAuthenticateHeaders_PicksSupported(string authenticateHeader, string supportedAuth, string unsupportedAuth) { if (PlatformDetection.IsWindowsNanoServer) { return; } var options = new LoopbackServer.Options { Domain = Domain, Username = Username, Password = Password }; await LoopbackServer.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.UseDefaultCredentials = false; var credentials = new CredentialCache(); credentials.Add(url, supportedAuth, new NetworkCredential(Username, Password, Domain)); credentials.Add(url, unsupportedAuth, new NetworkCredential(Username, Password, Domain)); Task serverTask = server.AcceptConnectionPerformAuthenticationAndCloseAsync(authenticateHeader); await TestHelper.WhenAllCompletedOrAnyFailed(CreateAndValidateRequest(handler, url, HttpStatusCode.OK, credentials), serverTask); }, options); }
public async Task HttpClientHandler_MultipleAuthenticateHeaders_PicksSupported(string authenticateHeader, string supportedAuth, string unsupportedAuth) { if (PlatformDetection.IsWindowsNanoServer || (IsCurlHandler && authenticateHeader.Contains("Digest"))) { // TODO: #28065: Fix failing authentication test cases on different httpclienthandlers. return; } var options = new LoopbackServer.Options { Domain = Domain, Username = Username, Password = Password }; await LoopbackServer.CreateServerAsync(async (server, url) => { StandardSocketsHttpHandler handler = CreateSocketsHttpHandler(); var credentials = new CredentialCache(); credentials.Add(url, supportedAuth, new NetworkCredential(Username, Password, Domain)); credentials.Add(url, unsupportedAuth, new NetworkCredential(Username, Password, Domain)); Task serverTask = server.AcceptConnectionPerformAuthenticationAndCloseAsync(authenticateHeader); await TestHelper.WhenAllCompletedOrAnyFailed(s_createAndValidateRequest(handler, url, HttpStatusCode.OK, credentials), serverTask); }, options); }
public async Task GetAsync_NoSpecifiedProtocol_DefaultsToTls12() { using (var handler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = LoopbackServer.AllowAllCertificates }) using (var client = new HttpClient(handler)) { var options = new LoopbackServer.Options { UseSsl = true }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( client.GetAsync(url), LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) => { Assert.Equal(SslProtocols.Tls12, Assert.IsType <SslStream>(stream).SslProtocol); await LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer); }, options)); }, options); } }
public async Task MaxResponseContentBufferSize_ThrowsIfTooSmallForContent(int maxSize, int contentLength, bool exceptionExpected) { using (HttpClient client = CreateHttpClient()) { client.MaxResponseContentBufferSize = maxSize; await LoopbackServer.CreateServerAsync(async (server, url) => { Task <string> getTask = client.GetStringAsync(url); Task serverTask = server.AcceptConnectionSendResponseAndCloseAsync(content: new string('s', contentLength)); Task bothTasks = TestHelper.WhenAllCompletedOrAnyFailed(getTask, serverTask); if (exceptionExpected) { await Assert.ThrowsAsync <HttpRequestException>(() => bothTasks); } else { await bothTasks; } }); } }
public async Task GetAsync_ReceiveSetCookieHeader_CookieUpdated() { const string newCookieValue = "789"; await LoopbackServer.CreateServerAsync(async (server, url) => { StandardSocketsHttpHandler handler = CreateSocketsHttpHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = new HttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <List <string> > serverTask = server.AcceptConnectionSendResponseAndCloseAsync( HttpStatusCode.OK, $"Set-Cookie: {s_cookieName}={newCookieValue}\r\n", s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(1, collection.Count); Assert.Equal(s_cookieName, collection[0].Name); Assert.Equal(newCookieValue, collection[0].Value); } }); }
public async Task GetAsync_ReceiveSetCookieHeader_CookieUpdated() { const string newCookieValue = "789"; await LoopbackServer.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = new HttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/1.1 200 Ok\r\nContent-Length: {s_simpleContent.Length}\r\nSet-Cookie: {s_cookieName}={newCookieValue}\r\n\r\n{s_simpleContent}"); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(1, collection.Count); Assert.Equal(s_cookieName, collection[0].Name); Assert.Equal(newCookieValue, collection[0].Value); } }); }
public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol) { using (var handler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = LoopbackServer.AllowAllCertificates }) using (var client = new HttpClient(handler)) { if (requestOnlyThisProtocol) { handler.SslProtocols = acceptedProtocol; } var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( LoopbackServer.ReadRequestAndSendResponseAsync(server, options: options), client.GetAsync(url)); }, options); } }
public async Task GetAsync_ResponseHasNormalLineEndings_Success(string lineEnding) { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <List <string> > serverTask = server.AcceptConnectionSendCustomResponseAndCloseAsync( $"HTTP/1.1 200 OK{lineEnding}Connection: close\r\nDate: {DateTimeOffset.UtcNow:R}{lineEnding}Server: TestServer{lineEnding}Content-Length: 0{lineEnding}{lineEnding}"); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(200, (int)response.StatusCode); Assert.Equal("OK", response.ReasonPhrase); Assert.Equal("TestServer", response.Headers.Server.ToString()); } } }, new LoopbackServer.Options { StreamWrapper = GetStream }); }
public async Task SetDelegate_ConnectionSucceeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol) { // Overriding flag for the same reason we skip tests on Catalina // On OSX 10.13-10.14 we can override this flag to enable the scenario // Issue: #22089 requestOnlyThisProtocol |= PlatformDetection.IsMacOsHighSierraOrHigher && acceptedProtocol == SslProtocols.Tls; if (PlatformDetection.IsMacOsCatalinaOrHigher && acceptedProtocol == SslProtocols.Tls && IsCurlHandler) { // Issue: #39989 // When the server uses SslProtocols.Tls, on MacOS, SecureTransport ends up picking a cipher suite // for TLS1.2, even though server said it was only using TLS1.0. LibreSsl throws error that // wrong cipher is used for TLS1.0. throw new SkipTestException("OSX may pick future cipher suites when asked for TLS1.0"); } using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; if (requestOnlyThisProtocol) { handler.SslProtocols = acceptedProtocol; } var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( server.AcceptConnectionSendResponseAndCloseAsync(), client.GetAsync(url)); }, options); } }
public async Task GetAsync_UnknownRequestVersion_ThrowsOrDegradesTo11(int majorVersion, int minorVersion) { Type exceptionType = null; if (PlatformDetection.IsFullFramework) { exceptionType = typeof(ArgumentException); } await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = new Version(majorVersion, minorVersion); Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/1.1 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n", new LoopbackServer.Options { ResponseStreamWrapper = GetStream_ClientDisconnectOk }); if (exceptionType == null) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); var requestLines = await serverTask; Assert.Equal($"GET {url.PathAndQuery} HTTP/1.1", requestLines[0]); } else { await Assert.ThrowsAsync(exceptionType, (() => TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask))); } } }); }
public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProtocol, bool requestOnlyThisProtocol) { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; if (requestOnlyThisProtocol) { handler.SslProtocols = acceptedProtocol; } else { // Explicitly setting protocols clears implementation default // restrictions on minimum TLS/SSL version // We currently know that some platforms like Debian 10 OpenSSL // will by default block < TLS 1.2 #pragma warning disable 0618 // SSL2/3 are deprecated #if !NETFRAMEWORK handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13; #else handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; #endif #pragma warning restore 0618 } var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( server.AcceptConnectionSendResponseAndCloseAsync(), client.GetAsync(url)); }, options); } }
public async Task GetAsync_AllowedSSLVersionDiffersFromServer_ThrowsException( SslProtocols allowedProtocol, SslProtocols acceptedProtocol, Type exceptedServerException) { if (!BackendSupportsSslConfiguration) { return; } using (HttpClientHandler handler = CreateHttpClientHandler()) using (var client = new HttpClient(handler)) { handler.SslProtocols = allowedProtocol; handler.ServerCertificateCustomValidationCallback = LoopbackServer.AllowAllCertificates; var options = new LoopbackServer.Options { UseSsl = true, SslProtocols = acceptedProtocol }; await LoopbackServer.CreateServerAsync(async (server, url) => { await TestHelper.WhenAllCompletedOrAnyFailed( Assert.ThrowsAsync(exceptedServerException, () => LoopbackServer.ReadRequestAndSendResponseAsync(server, options: options)), Assert.ThrowsAsync <HttpRequestException>(() => client.GetAsync(url))); }, options); } }
public async Task GetAsync_NoPathDefined_CookieAddedWithDefaultPath() { await LoopbackServerFactory.CreateServerAsync(async (server, serverUrl) => { Uri requestUrl = new Uri(serverUrl, "path/sub"); HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = CreateHttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(requestUrl); Task <HttpRequestData> serverTask = server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", "A=1"), }, s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); Cookie cookie = handler.CookieContainer.GetCookies(requestUrl)[0]; Assert.Equal("/path", cookie.Path); } }); }
public async Task GetAsync_ResponseUnknownVersion1X_Success(int responseMinorVersion) { bool reportAs00 = !UseSocketsHttpHandler; await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = HttpVersion.Version11; Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = server.AcceptConnectionSendCustomResponseAndCloseAsync( $"HTTP/1.{responseMinorVersion} 200 OK\r\nConnection: close\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n"); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { if (reportAs00) { Assert.Equal(0, response.Version.Major); Assert.Equal(0, response.Version.Minor); } else { Assert.Equal(1, response.Version.Major); Assert.Equal(responseMinorVersion, response.Version.Minor); } } } }, new LoopbackServer.Options { StreamWrapper = GetStream }); }
public async Task GetAsync_RequestVersion11_Success() { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = HttpVersion.Version11; Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/1.1 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n", new LoopbackServer.Options { ResponseStreamWrapper = GetStream }); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); var requestLines = await serverTask; Assert.Equal($"GET {url.PathAndQuery} HTTP/1.1", requestLines[0]); } }); }
private async Task GetAsyncSuccessHelper(string statusLine, int expectedStatusCode, string expectedReason) { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); await TestHelper.WhenAllCompletedOrAnyFailed( getResponseTask, LoopbackServer.ReadRequestAndSendResponseAsync(server, $"{statusLine}\r\n" + $"Date: {DateTimeOffset.UtcNow:R}\r\n" + "\r\n", new LoopbackServer.Options { ResponseStreamWrapper = GetStream })); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(expectedStatusCode, (int)response.StatusCode); Assert.Equal(expectedReason, response.ReasonPhrase); } } }); }
public async Task GetAsync_ResponseVersion0X_ThrowsOr10(int responseMinorVersion) { bool reportAs10 = PlatformDetection.IsFullFramework; await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Version = HttpVersion.Version11; Task <HttpResponseMessage> getResponseTask = client.SendAsync(request); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/0.{responseMinorVersion} 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n", new LoopbackServer.Options { ResponseStreamWrapper = GetStream_ClientDisconnectOk }); if (reportAs10) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(1, response.Version.Major); Assert.Equal(0, response.Version.Minor); } } else { await Assert.ThrowsAsync <HttpRequestException>(async() => await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask)); } } }); }
public async Task Manual_CertificateSentMatchesCertificateReceived_Success( int numberOfRequests, bool reuseClient) // validate behavior with and without connection pooling, which impacts client cert usage { if (!BackendSupportsCustomCertificateHandling) // can't use [Conditional*] right now as it's evaluated at the wrong time for SocketsHttpHandler { _output.WriteLine($"Skipping {nameof(Manual_CertificateSentMatchesCertificateReceived_Success)}()"); return; } var options = new LoopbackServer.Options { UseSsl = true }; Func <X509Certificate2, HttpClient> createClient = (cert) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.ServerCertificateCustomValidationCallback = delegate { return(true); }; handler.ClientCertificates.Add(cert); Assert.True(handler.ClientCertificates.Contains(cert)); return(new HttpClient(handler)); }; Func <HttpClient, LoopbackServer, Uri, X509Certificate2, Task> makeAndValidateRequest = async(client, server, url, cert) => { await TestHelper.WhenAllCompletedOrAnyFailed( client.GetStringAsync(url), server.AcceptConnectionAsync(async connection => { SslStream sslStream = Assert.IsType <SslStream>(connection.Stream); // We can't do Assert.Equal(cert, sslStream.RemoteCertificate) because // on .NET Framework sslStream.RemoteCertificate is always an X509Certificate // object which is not equal to the X509Certificate2 object we use in the tests. // So, we'll just compare a few properties to make sure it's the right certificate. Assert.Equal(cert.Subject, sslStream.RemoteCertificate.Subject); Assert.Equal(cert.Issuer, sslStream.RemoteCertificate.Issuer); await connection.ReadRequestHeaderAndSendResponseAsync(additionalHeaders: "Connection: close\r\n"); })); }; await LoopbackServer.CreateServerAsync(async (server, url) => { using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate()) { if (reuseClient) { using (HttpClient client = createClient(cert)) { for (int i = 0; i < numberOfRequests; i++) { await makeAndValidateRequest(client, server, url, cert); GC.Collect(); GC.WaitForPendingFinalizers(); } } } else { for (int i = 0; i < numberOfRequests; i++) { using (HttpClient client = createClient(cert)) { await makeAndValidateRequest(client, server, url, cert); } GC.Collect(); GC.WaitForPendingFinalizers(); } } } }, options); }