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 HttpClientHandler_Authentication_Succeeds(string authenticateHeader, bool result) { if (PlatformDetection.IsWindowsNanoServer || (IsCurlHandler && authenticateHeader.ToLowerInvariant().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) => { string serverAuthenticateHeader = $"WWW-Authenticate: {authenticateHeader}\r\n"; HttpClientHandler handler = CreateHttpClientHandler(); Task serverTask = result ? server.AcceptConnectionPerformAuthenticationAndCloseAsync(serverAuthenticateHeader) : server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.Unauthorized, serverAuthenticateHeader); await TestHelper.WhenAllCompletedOrAnyFailedWithTimeout(TestHelper.PassingTestTimeoutMilliseconds, s_createAndValidateRequest(handler, url, result ? HttpStatusCode.OK : HttpStatusCode.Unauthorized, s_credentials), serverTask); }, options); }
private static void CreateServerAndGet(HttpClient client, HttpCompletionOption completionOption, string responseText) { LoopbackServer.CreateServerAsync((server, url) => { Task <HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); server.AcceptConnectionAsync(connection => { while (!string.IsNullOrEmpty(connection.Reader.ReadLine())) { ; } connection.Writer.Write(responseText); connection.Socket.Shutdown(SocketShutdown.Send); return(Task.CompletedTask); }).GetAwaiter().GetResult(); getAsync.GetAwaiter().GetResult().Dispose(); return(Task.CompletedTask); }).GetAwaiter().GetResult(); }
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 }); }
private static void CreateServerAndGet(HttpClient client, HttpCompletionOption completionOption, string responseText) { LoopbackServer.CreateServerAsync((server, url) => { Task <HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); LoopbackServer.AcceptSocketAsync(server, (s, stream, reader, writer) => { while (!string.IsNullOrEmpty(reader.ReadLine())) { ; } writer.Write(responseText); s.Shutdown(SocketShutdown.Send); return(Task.FromResult <List <string> >(null)); }).GetAwaiter().GetResult(); getAsync.GetAwaiter().GetResult().Dispose(); return(Task.CompletedTask); }).GetAwaiter().GetResult(); }
public async Task ProxiedRequest_DefaultPort_PortStrippedOffInUri(string host) { string addressUri = $"http://{host}:80/"; string expectedAddressUri = $"http://{host}/"; bool connectionAccepted = false; await LoopbackServer.CreateClientAndServerAsync(async proxyUri => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.Proxy = new WebProxy(proxyUri); try { await client.GetAsync(addressUri); } catch { } } }, server => server.AcceptConnectionAsync(async connection => { connectionAccepted = true; List <string> headers = await connection.ReadRequestHeaderAndSendResponseAsync(); Assert.Contains($"GET {expectedAddressUri} HTTP/1.1", headers); })); Assert.True(connectionAccepted); }
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 AutomaticOrManual_DoesntFailRegardlessOfWhetherClientCertsAreAvailable(ClientCertificateOption mode) { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; handler.ClientCertificateOptions = mode; await LoopbackServer.CreateServerAsync(async server => { Task clientTask = client.GetStringAsync(server.Address); Task serverTask = server.AcceptConnectionAsync(async connection => { SslStream sslStream = Assert.IsType <SslStream>(connection.Stream); await connection.ReadRequestHeaderAndSendResponseAsync(); }); await new Task[] { clientTask, serverTask }.WhenAllOrAnyFailed(); }, new LoopbackServer.Options { UseSsl = true }); } }
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 = 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_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); } }
private static async Task CreateServerAndPostAsync(HttpClient client, int numBytes, string responseText) { await LoopbackServer.CreateServerAsync(async (server, url) => { var content = new ByteArrayContent(new byte[numBytes]); Task <HttpResponseMessage> postAsync = client.PostAsync(url, content); await server.AcceptConnectionAsync(async connection => { byte[] postData = new byte[numBytes]; while (!string.IsNullOrEmpty(await connection.ReadLineAsync().ConfigureAwait(false))) { ; } Assert.Equal(numBytes, await connection.ReadBlockAsync(postData, 0, numBytes)); await connection.Writer.WriteAsync(responseText).ConfigureAwait(false); connection.Socket.Shutdown(SocketShutdown.Send); }); (await postAsync.ConfigureAwait(false)).Dispose(); }); }
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 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_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 ThresholdExceeded_ThrowsException(string responseHeaders, int?maxResponseHeadersLength, bool shouldSucceed) { if (IsCurlHandler) { // libcurl often fails with out of memory errors return; } await LoopbackServer.CreateServerAsync(async (server, url) => { using (StandardSocketsHttpHandler handler = CreateSocketsHttpHandler()) using (var client = new HttpClient(handler)) { if (maxResponseHeadersLength.HasValue) { handler.MaxResponseHeadersLength = maxResponseHeadersLength.Value; } Task <HttpResponseMessage> getAsync = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); await server.AcceptConnectionAsync(async connection => { Task serverTask = connection.ReadRequestHeaderAndSendCustomResponseAsync(responseHeaders); if (shouldSucceed) { (await getAsync).Dispose(); await serverTask; } else { await Assert.ThrowsAsync <HttpRequestException>(() => getAsync); try { await serverTask; } catch { } } }); } }); }
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 PreAuthenticate_AuthenticatedUrl_ThenTryDifferentUrl_SendsAuthHeaderOnlyIfPrefixMatches( string originalRelativeUri, string secondRelativeUri, bool expectedAuthHeader) { const string AuthResponse = "WWW-Authenticate: Basic realm=\"hello\"\r\n"; await LoopbackServer.CreateClientAndServerAsync(async uri => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // for simplicity of not needing to know every handler's pooling policy handler.PreAuthenticate = true; handler.Credentials = s_credentials; Assert.Equal("hello world 1", await client.GetStringAsync(new Uri(uri, originalRelativeUri))); Assert.Equal("hello world 2", await client.GetStringAsync(new Uri(uri, secondRelativeUri))); } }, async server => { List <string> headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.Unauthorized, AuthResponse); Assert.All(headers, header => Assert.DoesNotContain("Authorization", header)); headers = await server.AcceptConnectionSendResponseAndCloseAsync(content: "hello world 1"); Assert.Contains(headers, header => header.Contains("Authorization")); headers = await server.AcceptConnectionSendResponseAndCloseAsync(content: "hello world 2"); if (expectedAuthHeader) { Assert.Contains(headers, header => header.Contains("Authorization")); } else { Assert.All(headers, header => Assert.DoesNotContain("Authorization", header)); } }); }
public async Task GetAsync_DontDisposeResponse_EventuallyUnblocksWaiters() { if (!UseSocketsHttpHandler) { // Issue #27067. Hang. return; } await LoopbackServer.CreateServerAsync(async (server, uri) => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = new HttpClient(handler)) { handler.MaxConnectionsPerServer = 1; // Let server handle two requests. const string Response = "HTTP/1.1 200 OK\r\nContent-Length: 26\r\n\r\nabcdefghijklmnopqrstuvwxyz"; Task serverTask1 = LoopbackServer.ReadRequestAndSendResponseAsync(server, Response); Task serverTask2 = LoopbackServer.ReadRequestAndSendResponseAsync(server, Response); // Make first request and drop the response, not explicitly disposing of it. void MakeAndDropRequest() => client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); // separated out to enable GC of response MakeAndDropRequest(); // A second request should eventually succeed, once the first one is cleaned up. Task <HttpResponseMessage> secondResponse = client.GetAsync(uri); Assert.True(SpinWait.SpinUntil(() => { GC.Collect(); GC.WaitForPendingFinalizers(); return(secondResponse.IsCompleted); }, 30 * 1000), "Expected second response to have completed"); await new[] { serverTask1, serverTask2, secondResponse }.WhenAllOrAnyFailed(); } }); }
public async Task GetAsyncWithRedirect_SetCookieContainer_CorrectCookiesSent() { const string path1 = "/foo"; const string path2 = "/bar"; await LoopbackServer.CreateServerAndClientAsync(async url => { Uri url1 = new Uri(url, path1); Uri url2 = new Uri(url, path2); Uri unusedUrl = new Uri(url, "/unused"); HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = new CookieContainer(); handler.CookieContainer.Add(url1, new Cookie("cookie1", "value1")); handler.CookieContainer.Add(url2, new Cookie("cookie2", "value2")); handler.CookieContainer.Add(unusedUrl, new Cookie("cookie3", "value3")); using (HttpClient client = new HttpClient(handler)) { await client.GetAsync(url1); } }, async server => { List <string> request1Lines = await LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/1.1 302 Found\r\nContent-Length: 0\r\nLocation: {path2}\r\nConnection: close\r\n\r\n"); Assert.Contains($"Cookie: cookie1=value1", request1Lines); Assert.Equal(1, request1Lines.Count(s => s.StartsWith("Cookie:"))); List <string> request2Lines = await LoopbackServer.ReadRequestAndSendResponseAsync(server, $"HTTP/1.1 200 OK\r\nContent-Length: {s_simpleContent.Length}\r\n\r\n{s_simpleContent}"); Assert.Contains($"Cookie: cookie2=value2", request2Lines); Assert.Equal(1, request2Lines.Count(s => s.StartsWith("Cookie:"))); }); }
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 PreAuthenticate_SuccessfulBasicButThenFails_DoesntLoopInfinitely() { await LoopbackServer.CreateClientAndServerAsync(async uri => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // for simplicity of not needing to know every handler's pooling policy handler.PreAuthenticate = true; handler.Credentials = s_credentials; // First two requests: initially without auth header, then with Assert.Equal("hello world", await client.GetStringAsync(uri)); // Attempt preauth, and when that fails, give up. using (HttpResponseMessage resp = await client.GetAsync(uri)) { Assert.Equal(HttpStatusCode.Unauthorized, resp.StatusCode); } } }, async server => { // First request, no auth header, challenge Basic List <string> headers = headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.Unauthorized, "WWW-Authenticate: Basic realm=\"hello\"\r\n"); Assert.All(headers, header => Assert.DoesNotContain("Authorization", header)); // Second request, contains Basic auth header headers = await server.AcceptConnectionSendResponseAndCloseAsync(content: "hello world"); Assert.Contains(headers, header => header.Contains("Authorization")); // Third request, contains Basic auth header but challenges anyway headers = headers = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.Unauthorized, "WWW-Authenticate: Basic realm=\"hello\"\r\n"); Assert.Contains(headers, header => header.Contains("Authorization")); }); }
public async Task GetAsync_AddMultipleCookieHeaders_CookiesSent() { if (IsNetfxHandler) { // Netfx handler does not support custom cookie header return; } await LoopbackServer.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = new HttpClient(handler)) { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, url); requestMessage.Headers.Add("Cookie", "A=1"); requestMessage.Headers.Add("Cookie", "B=2"); requestMessage.Headers.Add("Cookie", "C=3"); Task <HttpResponseMessage> getResponseTask = client.SendAsync(requestMessage); Task <List <string> > serverTask = LoopbackServer.ReadRequestAndSendResponseAsync(server); List <string> requestLines = await serverTask; Assert.Equal(1, requestLines.Count(s => s.StartsWith("Cookie: "))); // Multiple Cookie header values are treated as any other header values and are // concatenated using ", " as the separator. var cookieValues = requestLines.Single(s => s.StartsWith("Cookie: ")).Substring(8).Split(new string[] { ", " }, StringSplitOptions.None); Assert.Contains("A=1", cookieValues); Assert.Contains("B=2", cookieValues); Assert.Contains("C=3", cookieValues); Assert.Equal(3, cookieValues.Count()); } }); }
public async Task GetAsyncWithRedirect_SetCookieContainer_CorrectCookiesSent() { const string path1 = "/foo"; const string path2 = "/bar"; await LoopbackServer.CreateClientAndServerAsync(async url => { Uri url1 = new Uri(url, path1); Uri url2 = new Uri(url, path2); Uri unusedUrl = new Uri(url, "/unused"); HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = new CookieContainer(); handler.CookieContainer.Add(url1, new Cookie("cookie1", "value1")); handler.CookieContainer.Add(url2, new Cookie("cookie2", "value2")); handler.CookieContainer.Add(unusedUrl, new Cookie("cookie3", "value3")); using (HttpClient client = new HttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // to avoid issues with connection pooling await client.GetAsync(url1); } }, async server => { List <string> request1Lines = await server.AcceptConnectionSendResponseAndCloseAsync(HttpStatusCode.Found, $"Location: {path2}\r\n"); Assert.Contains($"Cookie: cookie1=value1", request1Lines); Assert.Equal(1, request1Lines.Count(s => s.StartsWith("Cookie:"))); List <string> request2Lines = await server.AcceptConnectionSendResponseAndCloseAsync(content: s_simpleContent); Assert.Contains($"Cookie: cookie2=value2", request2Lines); Assert.Equal(1, request2Lines.Count(s => s.StartsWith("Cookie:"))); }); }
public async Task ProxyTunnelRequest_OriginServerSendsProxyAuthChallenge_NoProxyAuthPerformed() { if (IsWinHttpHandler) { return; } using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create()) { HttpClientHandler handler = CreateHttpClientHandler(); handler.Proxy = new WebProxy(proxyServer.Uri) { Credentials = ConstructCredentials(new NetworkCredential("username", "password"), proxyServer.Uri, BasicAuth, true) }; handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; using (HttpClient client = CreateHttpClient(handler)) { var options = new LoopbackServer.Options { UseSsl = true }; await LoopbackServer.CreateServerAsync(async (server, uri) => { Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri)); Task <HttpResponseMessage> clientTask = client.GetAsync(uri); await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.ProxyAuthenticationRequired, additionalHeaders: "Proxy-Authenticate: Basic").WaitAsync(TestHelper.PassingTestTimeout); using (var response = await clientTask.WaitAsync(TestHelper.PassingTestTimeout)) { Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode); } }, options).WaitAsync(TestHelper.PassingTestTimeout); } Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine); } }
public async Task ProxyTunnelRequest_GetAsync_Success() { if (IsWinHttpHandler) { return; } const string Content = "Hello world"; using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create()) { HttpClientHandler handler = CreateHttpClientHandler(); handler.Proxy = new WebProxy(proxyServer.Uri); handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; using (HttpClient client = CreateHttpClient(handler)) { var options = new LoopbackServer.Options { UseSsl = true }; await LoopbackServer.CreateServerAsync(async (server, uri) => { Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri)); Task <HttpResponseMessage> clientTask = client.GetAsync(uri); await server.AcceptConnectionSendResponseAndCloseAsync(content: Content); using (var response = await clientTask) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(Content, await response.Content.ReadAsStringAsync()); } }, options); } Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine); } }
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 InfiniteSingleHeader_ThrowsException() { await LoopbackServer.CreateServerAsync(async (server, url) => { using (HttpClientHandler handler = CreateHttpClientHandler()) using (HttpClient client = CreateHttpClient(handler)) { Task <HttpResponseMessage> getAsync = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); await server.AcceptConnectionAsync(async connection => { var cts = new CancellationTokenSource(); Task serverTask = Task.Run(async delegate { await connection.ReadRequestHeaderAndSendCustomResponseAsync("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nMyInfiniteHeader: "); try { while (!cts.IsCancellationRequested) { await connection.Writer.WriteAsync(new string('s', 16000)); await Task.Delay(1); } } catch { } }); Exception e = await Assert.ThrowsAsync <HttpRequestException>(() => getAsync); cts.Cancel(); if (UseSocketsHttpHandler) { Assert.Contains((handler.MaxResponseHeadersLength * 1024).ToString(), e.ToString()); } await serverTask; }); } }); }
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); } }