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); }
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 = server.AcceptConnectionSendCustomResponseAndCloseAsync( $"HTTP/0.{responseMinorVersion} 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n"); 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)); } } }, new LoopbackServer.Options { StreamWrapper = GetStream_ClientDisconnectOk }); }
public async Task GetAsyncVersion11_BadResponseVersion_ThrowsOr00(int responseMajorVersion, int responseMinorVersion) { // Full framework reports 1.0 or 1.1, depending on minor version, instead of throwing bool reportAs1X = PlatformDetection.IsFullFramework; // CurlHandler reports these as 0.0, except for 2.0 which is reported as 2.0, instead of throwing. bool reportAs00 = false; bool reportAs20 = false; if (!PlatformDetection.IsWindows && !UseSocketsHttpHandler) { if (responseMajorVersion == 2 && responseMinorVersion == 0) { reportAs20 = true; } else { reportAs00 = true; } } 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/{responseMajorVersion}.{responseMinorVersion} 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n"); if (reportAs00) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(0, response.Version.Major); Assert.Equal(0, response.Version.Minor); } } else if (reportAs20) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(2, response.Version.Major); Assert.Equal(0, response.Version.Minor); } } else if (reportAs1X) { await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); using (HttpResponseMessage response = await getResponseTask) { Assert.Equal(1, response.Version.Major); Assert.Equal(responseMinorVersion == 0 ? 0 : 1, response.Version.Minor); } } else { await Assert.ThrowsAsync <HttpRequestException>(async() => await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask)); } } }, new LoopbackServer.Options { StreamWrapper = GetStream_ClientDisconnectOk }); }
public async Task Manual_CertificateSentMatchesCertificateReceived_Success( int numberOfRequests, bool reuseClient) // validate behavior with and without connection pooling, which impacts client cert usage { var options = new LoopbackServer.Options { UseSsl = true }; Func <X509Certificate2, HttpClient> createClient = (cert) => { var handler = new HttpClientHandler() { ServerCertificateCustomValidationCallback = delegate { return(true); } }; handler.ClientCertificates.Add(cert); return(new HttpClient(handler)); }; Func <HttpClient, Socket, Uri, X509Certificate2, Task> makeAndValidateRequest = async(client, server, url, cert) => { await TestHelper.WhenAllCompletedOrAnyFailed( client.GetStringAsync(url), LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) => { SslStream sslStream = Assert.IsType <SslStream>(stream); Assert.Equal(cert, sslStream.RemoteCertificate); await LoopbackServer.ReadWriteAcceptedAsync(socket, reader, writer); return(null); }, options)); }; await LoopbackServer.CreateServerAsync(async (server, url) => { if (reuseClient) { using (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate()) { 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 (X509Certificate2 cert = Configuration.Certificates.GetClientCertificate()) { using (HttpClient client = createClient(cert)) { await makeAndValidateRequest(client, server, url, cert); } } GC.Collect(); GC.WaitForPendingFinalizers(); } } }, options); }