Exemple #1
0
        public async Task ThresholdExceeded_ThrowsException(string responseHeaders, int maxResponseHeadersLength, bool shouldSucceed)
        {
            await LoopbackServer.CreateClientAndServerAsync(async (handler, client, server, url) =>
            {
                handler.MaxResponseHeadersLength    = maxResponseHeadersLength;
                Task <HttpResponseMessage> getAsync = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);

                await LoopbackServer.AcceptSocketAsync(server, async(s, serverStream, reader, writer) =>
                {
                    using (s) using (serverStream) using (reader) using (writer)
                                {
                                    string line;
                                    while ((line = reader.ReadLine()) != null && !string.IsNullOrEmpty(line))
                                    {
                                        ;
                                    }

                                    byte[] headerData = Encoding.ASCII.GetBytes(responseHeaders);
                                    serverStream.Write(headerData, 0, headerData.Length);
                                }

                    if (shouldSucceed)
                    {
                        (await getAsync).Dispose();
                    }
                    else
                    {
                        await Assert.ThrowsAsync <HttpRequestException>(() => getAsync);
                    }
                });
            });
        }
        public async Task UnreadResponseMessage_Collectible()
        {
            await LoopbackServer.CreateClientAndServerAsync(async (handler, client, server, url) =>
            {
                Func <Task <WeakReference> > getAsync = async() =>
                                                        new WeakReference(await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead));
                Task <WeakReference> wrt = getAsync();

                await LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) =>
                {
                    while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                    {
                        ;
                    }
                    await writer.WriteAsync(CreateResponse(new string('a', 32 * 1024)));
                    await writer.FlushAsync();

                    WeakReference wr = wrt.GetAwaiter().GetResult();
                    Assert.True(SpinWait.SpinUntil(() =>
                    {
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        GC.Collect();
                        return(!wr.IsAlive);
                    }, 10 * 1000), "Response object should have been collected");
                });
            });
        }
        public async Task GetAsync_NoSpecifiedProtocol_DefaultsToTls12()
        {
            if (!BackendSupportsSslConfiguration)
            {
                return;
            }
            using (HttpClientHandler handler = CreateHttpClientHandler())
                using (var client = new HttpClient(handler))
                {
                    handler.ServerCertificateCustomValidationCallback = LoopbackServer.AllowAllCertificates;

                    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);
                            return(null);
                        }, 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 LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) =>
                {
                    while (!string.IsNullOrEmpty(await reader.ReadLineAsync().ConfigureAwait(false)))
                    {
                        ;
                    }
                    for (int i = 0; i < numBytes; i++)
                    {
                        Assert.NotEqual(-1, reader.Read());
                    }

                    await writer.WriteAsync(responseText).ConfigureAwait(false);
                    await writer.FlushAsync().ConfigureAwait(false);
                    s.Shutdown(SocketShutdown.Send);
                });

                (await postAsync.ConfigureAwait(false)).Dispose();
            });
        }
Exemple #5
0
        public async Task GetAsync_CancelDuringResponseBodyReceived_Unbuffered_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, bool readOrCopyToAsync)
        {
            if (IsNetfxHandler || IsCurlHandler)
            {
                // doesn't cancel
                return;
            }

            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;
                var cts = new CancellationTokenSource();

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var clientFinished = new TaskCompletionSource <bool>();

                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }

                        await writer.WriteAsync(
                            $"HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            (!chunkedTransfer ? "Content-Length: 20\r\n" : "") +
                            (connectionClose ? "Connection: close\r\n" : "") +
                            $"\r\n");

                        await clientFinished.Task;

                        return(null);
                    });

                    var req = new HttpRequestMessage(HttpMethod.Get, url);
                    req.Headers.ConnectionClose            = connectionClose;
                    Task <HttpResponseMessage> getResponse = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, cts.Token);
                    await ValidateClientCancellationAsync(async() =>
                    {
                        HttpResponseMessage resp = await getResponse;
                        Stream respStream        = await resp.Content.ReadAsStreamAsync();
                        Task readTask            = readOrCopyToAsync ?
                                                   respStream.ReadAsync(new byte[1], 0, 1, cts.Token) :
                                                   respStream.CopyToAsync(Stream.Null, 10, cts.Token);
                        cts.Cancel();
                        await readTask;
                    });

                    try
                    {
                        clientFinished.SetResult(true);
                        await serverTask;
                    } catch { }
                });
            }
        }
        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
            };

            using (var cert = CertificateConfiguration.GetClientCertificate())
            {
                Func <HttpClient> createClient = () =>
                {
                    var handler = new HttpClientHandler()
                    {
                        ServerCertificateCustomValidationCallback = delegate { return(true); }
                    };
                    handler.ClientCertificates.Add(cert);
                    return(new HttpClient(handler));
                };

                Func <HttpClient, Socket, Uri, Task> makeAndValidateRequest = async(client, server, url) =>
                {
                    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);
                    }, options));
                };

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    if (reuseClient)
                    {
                        using (var client = createClient())
                        {
                            for (int i = 0; i < numberOfRequests; i++)
                            {
                                await makeAndValidateRequest(client, server, url);
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < numberOfRequests; i++)
                        {
                            using (var client = createClient())
                            {
                                await makeAndValidateRequest(client, server, url);
                            }
                        }
                    }
                }, options);
            }
        }
Exemple #7
0
        public async Task ReadAsStreamAsync_ReadAsync_Cancel_TaskCanceledQuickly(bool startResponseBody)
        {
            using (var client = new HttpClient())
            {
                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var triggerResponseWrite = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }
                        await writer.WriteAsync(
                            "HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            "Content-Length: 16000\r\n" +
                            "\r\n" +
                            (startResponseBody ? "20 bytes of the body" : ""));

                        await triggerResponseWrite.Task; // pause until we're released

                        return(null);
                    });

                    using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
                        using (Stream responseStream = await response.Content.ReadAsStreamAsync())
                        {
                            // Read all expected content
                            byte[] buffer = new byte[20];
                            if (startResponseBody)
                            {
                                int totalRead = 0;
                                int bytesRead;
                                while (totalRead < 20 && (bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                                {
                                    totalRead += bytesRead;
                                }
                            }

                            // Now do a read that'll need to be canceled
                            var stopwatch = Stopwatch.StartNew();
                            await Assert.ThrowsAnyAsync <OperationCanceledException>(
                                () => responseStream.ReadAsync(buffer, 0, buffer.Length, new CancellationTokenSource(1000).Token));
                            stopwatch.Stop();

                            triggerResponseWrite.SetResult(true);
                            _output.WriteLine("ReadAsync() completed at: {0}", stopwatch.Elapsed.ToString());
                            Assert.True(stopwatch.Elapsed < new TimeSpan(0, 0, 10), $"Elapsed time {stopwatch.Elapsed} should be short");
                        }
                });
            }
        }
Exemple #8
0
        public void SendAsync_ExpectedDiagnosticSourceNoLogging()
        {
            RemoteInvoke(() =>
            {
                bool requestLogged       = false;
                bool responseLogged      = false;
                bool activityStartLogged = false;
                bool activityStopLogged  = false;

                var diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
                {
                    if (kvp.Key.Equals("System.Net.Http.Request"))
                    {
                        requestLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.Response"))
                    {
                        responseLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.HttpRequestOut.Start"))
                    {
                        activityStartLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.HttpRequestOut.Stop"))
                    {
                        activityStopLogged = true;
                    }
                });

                using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
                {
                    using (var client = new HttpClient())
                    {
                        LoopbackServer.CreateServerAsync(async(server, url) =>
                        {
                            Task <List <string> > requestLines = LoopbackServer.AcceptSocketAsync(server,
                                                                                                  (s, stream, reader, writer) => LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer));
                            Task <HttpResponseMessage> response = client.GetAsync(url);
                            await Task.WhenAll(response, requestLines);

                            AssertNoHeadersAreInjected(requestLines.Result);
                            response.Result.Dispose();
                        }).Wait();
                    }

                    Assert.False(requestLogged, "Request was logged while logging disabled.");
                    Assert.False(activityStartLogged, "HttpRequestOut.Start was logged while logging disabled.");
                    WaitForFalse(() => responseLogged, TimeSpan.FromSeconds(1), "Response was logged while logging disabled.");
                    Assert.False(activityStopLogged, "HttpRequestOut.Stop was logged while logging disabled.");
                }
                return(SuccessExitCode);
            }).Dispose();
        }
Exemple #9
0
        public async Task GetAsync_ResponseContentRead_CancelUsingTimeoutOrToken_TaskCanceledQuickly(
            bool useTimeout, bool startResponseBody)
        {
            var               cts               = new CancellationTokenSource(); // ignored if useTimeout==true
            TimeSpan          timeout           = useTimeout ? new TimeSpan(0, 0, 1) : Timeout.InfiniteTimeSpan;
            CancellationToken cancellationToken = useTimeout ? CancellationToken.None : cts.Token;

            using (var client = new HttpClient()
            {
                Timeout = timeout
            })
            {
                var triggerResponseWrite = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                var triggerRequestCancel = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }
                        await writer.WriteAsync(
                            "HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            "Content-Length: 16000\r\n" +
                            "\r\n" +
                            (startResponseBody ? "less than 16000 bytes" : ""));

                        await Task.Delay(1000);
                        triggerRequestCancel.SetResult(true); // allow request to cancel
                        await triggerResponseWrite.Task;      // pause until we're released

                        return(null);
                    });

                    var stopwatch = Stopwatch.StartNew();
                    await Assert.ThrowsAnyAsync <OperationCanceledException>(async() =>
                    {
                        Task <HttpResponseMessage> getResponse = client.GetAsync(url, HttpCompletionOption.ResponseContentRead, cancellationToken);
                        await triggerRequestCancel.Task;
                        cts.Cancel();
                        await getResponse;
                    });
                    stopwatch.Stop();
                    _output.WriteLine("GetAsync() completed at: {0}", stopwatch.Elapsed.ToString());

                    triggerResponseWrite.SetResult(true);
                    Assert.True(stopwatch.Elapsed < new TimeSpan(0, 0, 10), $"Elapsed time {stopwatch.Elapsed} should be short");
                });
            }
        }
Exemple #10
0
        public async Task GetAsync_CancelDuringResponseBodyReceived_Buffered_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, CancellationMode mode)
        {
            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;
                var cts = new CancellationTokenSource();

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var responseHeadersSent = new TaskCompletionSource <bool>();
                    var clientFinished      = new TaskCompletionSource <bool>();

                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }

                        await writer.WriteAsync(
                            $"HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            (!chunkedTransfer ? "Content-Length: 20\r\n" : "") +
                            (connectionClose ? "Connection: close\r\n" : "") +
                            $"\r\n123"); // "123" is part of body and could either be chunked size or part of content-length bytes, both incomplete

                        responseHeadersSent.TrySetResult(true);
                        await clientFinished.Task;

                        return(null);
                    });

                    await ValidateClientCancellationAsync(async() =>
                    {
                        var req = new HttpRequestMessage(HttpMethod.Get, url);
                        req.Headers.ConnectionClose = connectionClose;

                        Task <HttpResponseMessage> getResponse = client.SendAsync(req, HttpCompletionOption.ResponseContentRead, cts.Token);
                        await responseHeadersSent.Task;
                        await Task.Delay(1); // make it more likely that client will have started processing response body
                        Cancel(mode, client, cts);
                        await getResponse;
                    });

                    try
                    {
                        clientFinished.SetResult(true);
                        await serverTask;
                    } catch { }
                });
            }
        }
Exemple #11
0
        public async Task PostAsync_CancelDuringRequestContentSend_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, CancellationMode mode)
        {
            if (IsWinHttpHandler || IsNetfxHandler)
            {
                // Issue #27063: hangs / doesn't cancel
                return;
            }

            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;
                var cts = new CancellationTokenSource();

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        // Since we won't receive all of the request, just read everything we do get
                        byte[] ignored = new byte[100];
                        while (await stream.ReadAsync(ignored, 0, ignored.Length) > 0)
                        {
                            ;
                        }
                        return(null);
                    });

                    var preContentSent  = new TaskCompletionSource <bool>();
                    var sendPostContent = new TaskCompletionSource <bool>();

                    await ValidateClientCancellationAsync(async() =>
                    {
                        var req     = new HttpRequestMessage(HttpMethod.Post, url);
                        req.Content = new DelayedByteContent(2000, 3000, preContentSent, sendPostContent.Task);
                        req.Headers.TransferEncodingChunked = chunkedTransfer;
                        req.Headers.ConnectionClose         = connectionClose;

                        Task <HttpResponseMessage> postResponse = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, cts.Token);
                        await preContentSent.Task;
                        Cancel(mode, client, cts);
                        await postResponse;
                    });

                    try
                    {
                        sendPostContent.SetResult(true);
                        await serverTask;
                    } catch { }
                });
            }
        }
        public async Task GetAsyncWithBasicAuth_ReceiveSetCookie_CookieSent()
        {
            if (IsWinHttpHandler)
            {
                // Issue #26986
                // WinHttpHandler does not process the cookie.
                return;
            }

            await LoopbackServer.CreateServerAndClientAsync(async url =>
            {
                HttpClientHandler handler = CreateHttpClientHandler();
                handler.Credentials       = new NetworkCredential("user", "pass");

                using (HttpClient client = new HttpClient(handler))
                {
                    await client.GetAsync(url);

                    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[2];
                    collection.CopyTo(cookies, 0);

                    Assert.Contains(cookies, c => c.Name == "A" && c.Value == "1");
                    Assert.Contains(cookies, c => c.Name == "B" && c.Value == "2");
                }
            },
                                                            async server =>
            {
                await LoopbackServer.AcceptSocketAsync(server, async(_, stream, reader, writer) =>
                {
                    List <string> request1Lines = await LoopbackServer.ReadWriteAcceptedAsync(server, reader, writer,
                                                                                              $"HTTP/1.1 401 Unauthorized\r\nContent-Length: 0\r\nWWW-Authenticate: Basic realm=\"WallyWorld\"\r\nSet-Cookie: A=1; Path=/\r\n\r\n");

                    Assert.Equal(0, request1Lines.Count(s => s.StartsWith("Cookie:")));

                    List <string> request2Lines = await LoopbackServer.ReadWriteAcceptedAsync(server, reader, writer,
                                                                                              $"HTTP/1.1 200 OK\r\nContent-Length: {s_simpleContent.Length}\r\nSet-Cookie: B=2; Path=/\r\n\r\n{s_simpleContent}");

                    Assert.Contains($"Cookie: A=1", request2Lines);
                    Assert.Equal(1, request2Lines.Count(s => s.StartsWith("Cookie:")));

                    return(null);
                });
            });
        }
Exemple #13
0
        public async Task GetAsync_CancelDuringResponseHeadersReceived_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, CancellationMode mode)
        {
            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;
                var cts = new CancellationTokenSource();

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var partialResponseHeadersSent = new TaskCompletionSource <bool>();
                    var clientFinished             = new TaskCompletionSource <bool>();

                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }

                        await writer.WriteAsync($"HTTP/1.1 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\n"); // missing final \r\n so headers don't complete

                        partialResponseHeadersSent.TrySetResult(true);
                        await clientFinished.Task;

                        return(null);
                    });

                    await ValidateClientCancellationAsync(async() =>
                    {
                        var req = new HttpRequestMessage(HttpMethod.Get, url);
                        req.Headers.ConnectionClose = connectionClose;

                        Task <HttpResponseMessage> getResponse = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, cts.Token);
                        await partialResponseHeadersSent.Task;
                        Cancel(mode, client, cts);
                        await getResponse;
                    });

                    try
                    {
                        clientFinished.SetResult(true);
                        await serverTask;
                    } catch { }
                });
            }
        }
Exemple #14
0
        public void SendAsync_ExpectedDiagnosticCancelledActivityLogging()
        {
            RemoteInvoke(() =>
            {
                bool cancelLogged = false;
                var diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
                {
                    if (kvp.Key == "System.Net.Http.HttpRequestOut.Stop")
                    {
                        Assert.NotNull(kvp.Value);
                        GetPropertyValueFromAnonymousTypeInstance <HttpRequestMessage>(kvp.Value, "Request");
                        var status = GetPropertyValueFromAnonymousTypeInstance <TaskStatus>(kvp.Value, "RequestTaskStatus");
                        Assert.Equal(TaskStatus.Canceled, status);
                        cancelLogged = true;
                    }
                });

                using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
                {
                    diagnosticListenerObserver.Enable();
                    using (var client = new HttpClient())
                    {
                        LoopbackServer.CreateServerAsync(async(server, url) =>
                        {
                            CancellationTokenSource tcs = new CancellationTokenSource();
                            Task request = LoopbackServer.AcceptSocketAsync(server,
                                                                            (s, stream, reader, writer) =>
                            {
                                tcs.Cancel();
                                return(LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer));
                            });
                            Task response = client.GetAsync(url, tcs.Token);
                            await Assert.ThrowsAnyAsync <Exception>(() => Task.WhenAll(response, request));
                        }).Wait();
                    }
                }
                // Poll with a timeout since logging response is not synchronized with returning a response.
                WaitForTrue(() => cancelLogged, TimeSpan.FromSeconds(1),
                            "Cancellation was not logged within 1 second timeout.");
                diagnosticListenerObserver.Disable();

                return(SuccessExitCode);
            }).Dispose();
        }
Exemple #15
0
        public async Task InfiniteSingleHeader_ThrowsException()
        {
            if (IsCurlHandler)
            {
                // libcurl fails with an out of memory error
                return;
            }

            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                using (HttpClientHandler handler = CreateHttpClientHandler())
                    using (var client = new HttpClient(handler))
                    {
                        Task <HttpResponseMessage> getAsync = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
                        await LoopbackServer.AcceptSocketAsync(server, async(s, serverStream, reader, writer) =>
                        {
                            var cts         = new CancellationTokenSource();
                            Task serverTask = Task.Run(async delegate
                            {
                                while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                                {
                                    ;
                                }
                                await writer.WriteAsync("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nMyInfiniteHeader: ");
                                try
                                {
                                    while (!cts.IsCancellationRequested)
                                    {
                                        await writer.WriteAsync(new string('s', 16000));
                                        await Task.Delay(1);
                                    }
                                }
                                catch { }
                            });

                            await Assert.ThrowsAsync <HttpRequestException>(() => getAsync);
                            cts.Cancel();
                            await serverTask;
                            return(null);
                        });
                    }
            });
        }
Exemple #16
0
        public void SendAsync_ExpectedDiagnosticCancelledLogging()
        {
            RemoteInvoke(useManagedHandlerString =>
            {
                bool cancelLogged = false;
                var diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
                {
                    if (kvp.Key.Equals("System.Net.Http.Response"))
                    {
                        Assert.NotNull(kvp.Value);
                        var status = GetPropertyValueFromAnonymousTypeInstance <TaskStatus>(kvp.Value, "RequestTaskStatus");
                        Assert.Equal(TaskStatus.Canceled, status);
                        Volatile.Write(ref cancelLogged, true);
                    }
                });

                using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
                {
                    diagnosticListenerObserver.Enable(s => !s.Contains("HttpRequestOut"));
                    using (HttpClient client = CreateHttpClient(useManagedHandlerString))
                    {
                        LoopbackServer.CreateServerAsync(async(server, url) =>
                        {
                            CancellationTokenSource tcs = new CancellationTokenSource();
                            Task request = LoopbackServer.AcceptSocketAsync(server,
                                                                            (s, stream, reader, writer) =>
                            {
                                tcs.Cancel();
                                return(LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer));
                            });
                            Task response = client.GetAsync(url, tcs.Token);
                            await Assert.ThrowsAnyAsync <Exception>(() => TestHelper.WhenAllCompletedOrAnyFailed(response, request));
                        }).Wait();
                    }
                }
                // Poll with a timeout since logging response is not synchronized with returning a response.
                WaitForTrue(() => Volatile.Read(ref cancelLogged), TimeSpan.FromSeconds(1),
                            "Cancellation was not logged within 1 second timeout.");
                diagnosticListenerObserver.Disable();

                return(SuccessExitCode);
            }, UseManagedHandler.ToString()).Dispose();
        }
        private static async Task CreateServerAndGetAsync(HttpClient client, HttpCompletionOption completionOption, string responseText)
        {
            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                Task <HttpResponseMessage> getAsync = client.GetAsync(url, completionOption);

                await LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) =>
                {
                    while (!string.IsNullOrEmpty(await reader.ReadLineAsync().ConfigureAwait(false)))
                    {
                        ;
                    }

                    await writer.WriteAsync(responseText).ConfigureAwait(false);
                    s.Shutdown(SocketShutdown.Send);
                });

                (await getAsync.ConfigureAwait(false)).Dispose();
            });
        }
        public async Task GetAsync_RetryOnConnectionClosed_Success()
        {
            if (!IsRetrySupported)
            {
                return;
            }

            await LoopbackServer.CreateServerAndClientAsync(async url =>
            {
                using (HttpClient client = CreateHttpClient())
                {
                    // Send initial request and receive response so connection is established
                    HttpResponseMessage response1 = await client.GetAsync(url);
                    Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
                    Assert.Equal(s_simpleContent, await response1.Content.ReadAsStringAsync());

                    // Send second request.  Should reuse same connection.
                    // The server will close the connection, but HttpClient should retry the request.
                    HttpResponseMessage response2 = await client.GetAsync(url);
                    Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
                    Assert.Equal(s_simpleContent, await response1.Content.ReadAsStringAsync());
                }
            },
                                                            async server =>
            {
                await LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) =>
                {
                    // Initial response
                    await LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer, s_simpleResponse);

                    // Second response: Read request headers, then close connection
                    await LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer, "");
                    s.Close();

                    // Client should reconnect.  Accept that connection and send response.
                    await LoopbackServer.ReadRequestAndSendResponseAsync(server, s_simpleResponse);

                    return(null);
                });
            });
        }
Exemple #19
0
        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 (HttpClientHandler handler = CreateHttpClientHandler())
                    using (var client = new HttpClient(handler))
                    {
                        if (maxResponseHeadersLength.HasValue)
                        {
                            handler.MaxResponseHeadersLength = maxResponseHeadersLength.Value;
                        }
                        Task <HttpResponseMessage> getAsync = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);

                        await LoopbackServer.AcceptSocketAsync(server, async(s, serverStream, reader, writer) =>
                        {
                            Task serverTask = LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer, responseHeaders);

                            if (shouldSucceed)
                            {
                                (await getAsync).Dispose();
                                await serverTask;
                            }
                            else
                            {
                                await Assert.ThrowsAsync <HttpRequestException>(() => getAsync);
                                try { await serverTask; } catch { }
                            }

                            return(null);
                        });
                    }
            });
        }
Exemple #20
0
        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 Manual_CertificateSentMatchesCertificateReceived_Success(
            int numberOfRequests,
            bool reuseClient) // validate behavior with and without connection pooling, which impacts client cert usage
        {
            if (BackendDoesNotSupportCustomCertificateHandling) // can't use [Conditional*] right now as it's evaluated at the wrong time for the managed handler
            {
                _output.WriteLine($"Skipping {nameof(Manual_CertificateSentMatchesCertificateReceived_Success)}()");
                return;
            }

            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);
        }
        public async Task PostAsyncExpect100Continue_RetryOnConnectionClosed_Success()
        {
            if (!IsRetrySupported)
            {
                return;
            }

            await LoopbackServer.CreateServerAndClientAsync(async url =>
            {
                using (HttpClient client = CreateHttpClient())
                {
                    // Send initial request and receive response so connection is established
                    HttpResponseMessage response1 = await client.GetAsync(url);
                    Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
                    Assert.Equal(s_simpleContent, await response1.Content.ReadAsStringAsync());

                    // Send second request.  Should reuse same connection.
                    // The server will close the connection, but HttpClient should retry the request.
                    HttpRequestMessage request     = new HttpRequestMessage(HttpMethod.Post, url);
                    request.Headers.ExpectContinue = true;
                    var content     = new CustomContent();
                    request.Content = content;

                    HttpResponseMessage response2 = await client.SendAsync(request);
                    Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
                    Assert.Equal(s_simpleContent, await response1.Content.ReadAsStringAsync());

                    Assert.Equal(1, content.SerializeCount);
                }
            },
                                                            async server =>
            {
                await LoopbackServer.AcceptSocketAsync(server, async(s, stream, reader, writer) =>
                {
                    // Initial response
                    await LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer, s_simpleResponse);

                    // Second response: Read request headers, then close connection
                    List <string> lines = await LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer, "");
                    Assert.Contains("Expect: 100-continue", lines);
                    s.Close();

                    // Client should reconnect.  Accept that connection and send response.
                    await LoopbackServer.AcceptSocketAsync(server, async(s2, stream2, reader2, writer2) =>
                    {
                        List <string> lines2 = await LoopbackServer.ReadWriteAcceptedAsync(s2, reader2, writer2, "");
                        Assert.Contains("Expect: 100-continue", lines2);

                        await writer2.WriteAsync("HTTP/1.1 100 Continue\r\n\r\n");

                        string contentLine = await reader2.ReadLineAsync();
                        Assert.Equal(s_simpleContent, contentLine + "\r\n");

                        await writer2.WriteAsync(s_simpleResponse);

                        return(null);
                    });

                    return(null);
                });
            });
        }
Exemple #23
0
        public async Task GetAsync_CancelPendingRequests_DoesntCancelReadAsyncOnResponseStream(CancellationMode mode, bool copyToAsync)
        {
            if (IsNetfxHandler)
            {
                // throws ObjectDisposedException as part of Stream.CopyToAsync/ReadAsync
                return;
            }
            if (IsCurlHandler)
            {
                // Issue #27065
                // throws OperationCanceledException from Stream.CopyToAsync/ReadAsync
                return;
            }

            using (HttpClient client = CreateHttpClient())
            {
                client.Timeout = Timeout.InfiniteTimeSpan;

                await LoopbackServer.CreateServerAsync(async (server, url) =>
                {
                    var clientReadSomeBody = new TaskCompletionSource <bool>();
                    var clientFinished     = new TaskCompletionSource <bool>();

                    var responseContentSegment = new string('s', 3000);
                    int responseSegments       = 4;
                    int contentLength          = responseContentSegment.Length * responseSegments;

                    Task serverTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                    {
                        while (!string.IsNullOrEmpty(await reader.ReadLineAsync()))
                        {
                            ;
                        }

                        await writer.WriteAsync(
                            $"HTTP/1.1 200 OK\r\n" +
                            $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
                            $"Content-Length: {contentLength}\r\n" +
                            $"\r\n");

                        for (int i = 0; i < responseSegments; i++)
                        {
                            await writer.WriteAsync(responseContentSegment);
                            if (i == 0)
                            {
                                await clientReadSomeBody.Task;
                            }
                        }

                        await clientFinished.Task;

                        return(null);
                    });


                    using (HttpResponseMessage resp = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
                        using (Stream respStream = await resp.Content.ReadAsStreamAsync())
                        {
                            var result = new MemoryStream();
                            int b      = respStream.ReadByte();
                            Assert.NotEqual(-1, b);
                            result.WriteByte((byte)b);

                            Cancel(mode, client, null); // should not cancel the operation, as using ResponseHeadersRead
                            clientReadSomeBody.SetResult(true);

                            if (copyToAsync)
                            {
                                await respStream.CopyToAsync(result, 10, new CancellationTokenSource().Token);
                            }
                            else
                            {
                                byte[] buffer = new byte[10];
                                int bytesRead;
                                while ((bytesRead = await respStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                                {
                                    result.Write(buffer, 0, bytesRead);
                                }
                            }

                            Assert.Equal(contentLength, result.Length);
                        }

                    clientFinished.SetResult(true);
                    await serverTask;
                });
            }
        }
Exemple #24
0
        public void SendAsync_ExpectedDiagnosticSourceActivityLogging()
        {
            RemoteInvoke(() =>
            {
                bool requestLogged       = false;
                bool responseLogged      = false;
                bool activityStartLogged = false;
                bool activityStopLogged  = false;
                bool exceptionLogged     = false;

                Activity parentActivity = new Activity("parent");
                parentActivity.AddBaggage("correlationId", Guid.NewGuid().ToString());
                parentActivity.AddBaggage("moreBaggage", Guid.NewGuid().ToString());
                parentActivity.AddTag("tag", "tag"); //add tag to ensure it is not injected into request
                parentActivity.Start();

                var diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
                {
                    if (kvp.Key.Equals("System.Net.Http.Request"))
                    {
                        requestLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.Response"))
                    {
                        responseLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.Exception"))
                    {
                        exceptionLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.HttpRequestOut.Start"))
                    {
                        Assert.NotNull(kvp.Value);
                        Assert.NotNull(Activity.Current);
                        Assert.Equal(parentActivity, Activity.Current.Parent);
                        GetPropertyValueFromAnonymousTypeInstance <HttpRequestMessage>(kvp.Value, "Request");

                        activityStartLogged = true;
                    }
                    else if (kvp.Key.Equals("System.Net.Http.HttpRequestOut.Stop"))
                    {
                        Assert.NotNull(kvp.Value);
                        Assert.NotNull(Activity.Current);
                        Assert.Equal(parentActivity, Activity.Current.Parent);
                        Assert.True(Activity.Current.Duration != TimeSpan.Zero);
                        GetPropertyValueFromAnonymousTypeInstance <HttpRequestMessage>(kvp.Value, "Request");
                        GetPropertyValueFromAnonymousTypeInstance <HttpResponseMessage>(kvp.Value, "Response");
                        var requestStatus = GetPropertyValueFromAnonymousTypeInstance <TaskStatus>(kvp.Value, "RequestTaskStatus");
                        Assert.Equal(TaskStatus.RanToCompletion, requestStatus);

                        activityStopLogged = true;
                    }
                });

                using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
                {
                    diagnosticListenerObserver.Enable();
                    using (var client = new HttpClient())
                    {
                        LoopbackServer.CreateServerAsync(async(server, url) =>
                        {
                            Task <List <string> > requestLines = LoopbackServer.AcceptSocketAsync(server,
                                                                                                  (s, stream, reader, writer) => LoopbackServer.ReadWriteAcceptedAsync(s, reader, writer));
                            Task response = client.GetAsync(url);
                            await Task.WhenAll(response, requestLines);

                            AssertHeadersAreInjected(requestLines.Result, parentActivity);
                        }).Wait();
                    }

                    Assert.True(activityStartLogged, "HttpRequestOut.Start was not logged.");
                    Assert.False(requestLogged, "Request was logged when Activity logging was enabled.");
                    // Poll with a timeout since logging response is not synchronized with returning a response.
                    WaitForTrue(() => activityStopLogged, TimeSpan.FromSeconds(1), "HttpRequestOut.Stop was not logged within 1 second timeout.");
                    Assert.False(exceptionLogged, "Exception was logged for successful request");
                    Assert.False(responseLogged, "Response was logged when Activity logging was enabled.");
                    diagnosticListenerObserver.Disable();
                }

                return(SuccessExitCode);
            }).Dispose();
        }
Exemple #25
0
        public async Task MaxConnectionsPerServer_WaitingConnectionsAreCancelable()
        {
            if (IsWinHttpHandler)
            {
                // Issue #27064:
                // Throws WinHttpException ("The server returned an invalid or unrecognized response")
                // while parsing headers.
                return;
            }
            if (IsNetfxHandler)
            {
                // Throws HttpRequestException wrapping a WebException for the canceled request
                // instead of throwing an OperationCanceledException or a canceled WebException directly.
                return;
            }

            using (HttpClientHandler handler = CreateHttpClientHandler())
                using (HttpClient client = new HttpClient(handler))
                {
                    handler.MaxConnectionsPerServer = 1;
                    client.Timeout = Timeout.InfiniteTimeSpan;

                    await LoopbackServer.CreateServerAsync(async (server, url) =>
                    {
                        var serverAboutToBlock  = new TaskCompletionSource <bool>();
                        var blockServerResponse = new TaskCompletionSource <bool>();

                        Task serverTask1 = LoopbackServer.AcceptSocketAsync(server, async(socket1, stream1, reader1, writer1) =>
                        {
                            while (!string.IsNullOrEmpty(await reader1.ReadLineAsync()))
                            {
                                ;
                            }
                            await writer1.WriteAsync($"HTTP/1.1 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\n");
                            serverAboutToBlock.SetResult(true);
                            await blockServerResponse.Task;
                            await writer1.WriteAsync("Content-Length: 5\r\n\r\nhello");
                            return(null);
                        });

                        Task get1 = client.GetAsync(url);
                        await serverAboutToBlock.Task;

                        var cts   = new CancellationTokenSource();
                        Task get2 = ValidateClientCancellationAsync(() => client.GetAsync(url, cts.Token));
                        Task get3 = ValidateClientCancellationAsync(() => client.GetAsync(url, cts.Token));

                        Task get4 = client.GetAsync(url);

                        cts.Cancel();
                        await get2;
                        await get3;

                        blockServerResponse.SetResult(true);
                        await new[] { get1, serverTask1 }.WhenAllOrAnyFailed();

                        Task serverTask4 = LoopbackServer.AcceptSocketAsync(server, async(socket2, stream2, reader2, writer2) =>
                        {
                            while (!string.IsNullOrEmpty(await reader2.ReadLineAsync()))
                            {
                                ;
                            }
                            await writer2.WriteAsync($"HTTP/1.1 200 OK\r\nDate: {DateTimeOffset.UtcNow:R}\r\nContent-Length: 0\r\n\r\n");
                            return(null);
                        });

                        await new[] { get4, serverTask4 }.WhenAllOrAnyFailed();
                    });
                }
        }