public async Task GetAsync_MissingExpires_ReturnNull() { await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) { HttpResponseMessage response = await client.GetAsync(uri); Assert.Null(response.Content.Headers.Expires); } }, async server => { await server.HandleRequestAsync(HttpStatusCode.OK); }); }
private async Task CreateServerAndGetAsync(HttpClient client, HttpCompletionOption completionOption, List <HttpHeaderData> headers, string content) { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { Task <HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); await new Task[] { getAsync, server.HandleRequestAsync(HttpStatusCode.OK, headers, content), }.WhenAllOrAnyFailed().ConfigureAwait(false); getAsync.Result.Dispose(); }); }
private void CreateServerAndGet(HttpClient client, HttpCompletionOption completionOption, List <HttpHeaderData> headers, string content) { LoopbackServerFactory.CreateServerAsync((server, url) => { Task <HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); new Task[] { getAsync, server.HandleRequestAsync(HttpStatusCode.OK, headers, content) }.WhenAllOrAnyFailed().GetAwaiter().GetResult(); getAsync.Result.Dispose(); return(Task.CompletedTask); }).GetAwaiter().GetResult(); }
public async Task GetAsync_DefaultCoookieContainer_NoCookieSent() { await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { using (HttpClient client = CreateHttpClient()) { await client.GetAsync(uri); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(); Assert.Equal(0, requestData.GetHeaderValueCount("Cookie")); }); }
public async Task PostAsync_CancelDuringRequestContentSend_TaskCanceledQuickly(bool chunkedTransfer, CancellationMode mode) { if (LoopbackServerFactory.IsHttp2 && chunkedTransfer) { // There is no chunked encoding in HTTP/2 return; } var serverRelease = new TaskCompletionSource <bool>(); await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { try { using (HttpClient client = CreateHttpClient()) { client.Timeout = Timeout.InfiniteTimeSpan; var cts = new CancellationTokenSource(); var waitToSend = new TaskCompletionSource <bool>(); var contentSending = new TaskCompletionSource <bool>(); var req = new HttpRequestMessage(HttpMethod.Post, uri) { Version = VersionFromUseHttp2 }; req.Content = new ByteAtATimeContent(int.MaxValue, waitToSend.Task, contentSending, millisecondDelayBetweenBytes: 1); req.Headers.TransferEncodingChunked = chunkedTransfer; Task <HttpResponseMessage> resp = client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, cts.Token); waitToSend.SetResult(true); await contentSending.Task; Cancel(mode, client, cts); await ValidateClientCancellationAsync(() => resp); } } finally { serverRelease.SetResult(true); } }, async server => { try { await server.AcceptConnectionAsync(connection => serverRelease.Task); } catch { }; // Ignore any closing errors since we did not really process anything. }); }
public async Task GetAsync_Redirect_CookiesArePreserved() { if (UseVersion == HttpVersion30) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/56870")] return; } HttpClientHandler handler = CreateHttpClientHandler(); string loginPath = "/login/user"; string returnPath = "/return"; await LoopbackServerFactory.CreateClientAndServerAsync(async serverUrl => { Uri loginUrl = new Uri(serverUrl, loginPath); Uri returnUrl = new Uri(serverUrl, returnPath); CookieContainer cookies = handler.CookieContainer; using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // to avoid issues with connection pooling HttpResponseMessage response = await client.GetAsync(loginUrl); string content = await response.Content.ReadAsStringAsync(); Assert.Equal(s_simpleContent, content); Cookie cookie = handler.CookieContainer.GetCookies(returnUrl)[0]; Assert.Equal("LoggedIn", cookie.Name); } }, async server => { HttpRequestData requestData1 = await server.HandleRequestAsync(HttpStatusCode.Found, new[] { new HttpHeaderData("Location", returnPath), new HttpHeaderData("Set-Cookie", "LoggedIn=true; Path=/return"), }); Assert.Equal(0, requestData1.GetHeaderValueCount("Cookie")); HttpRequestData requestData2 = await server.HandleRequestAsync(content: s_simpleContent, headers: new[] { new HttpHeaderData("Set-Cookie", "LoggedIn=true; Path=/return"), }); Assert.Equal("LoggedIn=true", requestData2.GetSingleHeaderValue("Cookie")); }); }
public async Task GetAsyncWithBasicAuth_ReceiveSetCookie_CookieSent() { await LoopbackServerFactory.CreateClientAndServerAsync(async url => { HttpClientHandler handler = CreateHttpClientHandler(); handler.Credentials = new NetworkCredential("user", "pass"); using (HttpClient client = CreateHttpClient(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 => { HttpRequestData requestData1 = await server.HandleRequestAsync( HttpStatusCode.Unauthorized, new HttpHeaderData[] { new HttpHeaderData("WWW-Authenticate", "Basic realm=\"WallyWorld\""), new HttpHeaderData("Set-Cookie", "A=1; Path=/") }); Assert.Equal(0, requestData1.GetHeaderValueCount("Cookie")); HttpRequestData requestData2 = await server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", "B=2; Path=/") }, s_simpleContent); Assert.Equal("A=1", requestData2.GetSingleHeaderValue("Cookie")); }); }
public async Task GetAsync_CancelDuringResponseHeadersReceived_TaskCanceledQuickly(bool connectionClose, CancellationMode mode) { if (LoopbackServerFactory.IsHttp2 && connectionClose) { // There is no Connection header in HTTP/2 return; } using (HttpClient client = CreateHttpClient()) { client.Timeout = Timeout.InfiniteTimeSpan; var cts = new CancellationTokenSource(); await LoopbackServerFactory.CreateServerAsync(async (server, url) => { var partialResponseHeadersSent = new TaskCompletionSource<bool>(); var clientFinished = new TaskCompletionSource<bool>(); Task serverTask = server.AcceptConnectionAsync(async connection => { await connection.ReadRequestDataAsync(); await connection.SendResponseAsync(HttpStatusCode.OK, content: null, isFinal: false); partialResponseHeadersSent.TrySetResult(true); await clientFinished.Task; }); await ValidateClientCancellationAsync(async () => { var req = new HttpRequestMessage(HttpMethod.Get, url) { Version = VersionFromUseHttp2 }; 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 { } }); } }
public async Task GetAsync_SetCookieContainerAndCookieHeader_BothCookiesSent() { if (IsNetfxHandler) { // Netfx handler does not support custom cookie header return; } if (IsCurlHandler) { // CurlHandler ignores container cookies when custom Cookie header is set. // SocketsHttpHandler behaves the expected way. Not worth fixing in CurlHandler as it is going away. return; } if (LoopbackServerFactory.IsHttp2 && UseSocketsHttpHandler) { // ISSUE #34377: We are not handling multi-valued headers correctly return; } await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = new HttpClient(handler)) { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, url); requestMessage.Headers.Add("Cookie", s_customCookieHeaderValue); Task <HttpResponseMessage> getResponseTask = client.SendAsync(requestMessage); Task <HttpRequestData> serverTask = server.HandleRequestAsync(); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); HttpRequestData requestData = await serverTask; string cookieHeaderValue = requestData.GetSingleHeaderValue("Cookie"); var cookies = cookieHeaderValue.Split(new string[] { "; " }, StringSplitOptions.None); Assert.Contains(s_expectedCookieHeaderValue, cookies); Assert.Contains(s_customCookieHeaderValue, cookies); Assert.Equal(2, cookies.Count()); } }); }
[InlineData("Max-Forwards", "NotAnInteger", false)] // invalid format for header but added with TryAddWithoutValidation public async Task SendAsync_SpecialHeaderKeyOrValue_Success(string key, string value, bool parsable) { if (PlatformDetection.IsBrowser && (key == "Content-Location" || key == "Date" || key == "Accept-CharSet")) { // https://fetch.spec.whatwg.org/#forbidden-header-name return; } await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { bool contentHeader = false; using (HttpClient client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; if (!message.Headers.TryAddWithoutValidation(key, value)) { message.Content = new StringContent(""); contentHeader = message.Content.Headers.TryAddWithoutValidation(key, value); } (await client.SendAsync(TestAsync, message).ConfigureAwait(false)).Dispose(); } // Validate our test by validating our understanding of a header's parsability. HttpHeaders headers = contentHeader ? (HttpHeaders) new StringContent("").Headers : new HttpRequestMessage().Headers; if (parsable) { headers.Add(key, value); } else { Assert.Throws <FormatException>(() => headers.Add(key, value)); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK); Assert.Equal(value, requestData.GetSingleHeaderValue(key)); }); }
public async Task GetAsync_AddMultipleCookieHeaders_CookiesSent() { if (IsNetfxHandler) { // Netfx handler does not support custom cookie header return; } if (LoopbackServerFactory.IsHttp2 && UseSocketsHttpHandler) { // ISSUE #34377: We are not handling multi-valued headers correctly return; } await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = new HttpClient(handler)) { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); requestMessage.Headers.Add("Cookie", "A=1"); requestMessage.Headers.Add("Cookie", "B=2"); requestMessage.Headers.Add("Cookie", "C=3"); await client.SendAsync(requestMessage); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(); // Multiple Cookie header values are treated as any other header values and are // concatenated using ", " as the separator. string cookieHeaderValue = requestData.GetSingleHeaderValue("Cookie"); var cookieValues = cookieHeaderValue.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 SendAsync_Expires_Success(string value, bool isValid) { await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (var client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri); HttpResponseMessage response = await client.SendAsync(message); Assert.NotNull(response.Content.Headers.Expires); // Invalid date should be converted to MinValue so everything is expired. Assert.Equal(isValid ? DateTime.Parse(value) : DateTimeOffset.MinValue, response.Content.Headers.Expires); } }, async server => { IList <HttpHeaderData> headers = new HttpHeaderData[] { new HttpHeaderData("Expires", value) }; HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK, headers); }); }
public async Task SendAsync_SpecialCharacterHeader_Success() { string headerValue = "header name with underscore"; await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (var client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri); message.Headers.TryAddWithoutValidation("x-Special_name", "header name with underscore"); (await client.SendAsync(message).ConfigureAwait(false)).Dispose(); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK); string header = requestData.GetSingleHeaderValue("x-Special_name"); Assert.Equal(header, headerValue); }); }
public async Task GetAsync_AddCookieHeader_CookieHeaderSent() { await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = new HttpClient(handler)) { HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); requestMessage.Headers.Add("Cookie", s_customCookieHeaderValue); await client.SendAsync(requestMessage); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(); Assert.Equal(s_customCookieHeaderValue, requestData.GetSingleHeaderValue("Cookie")); }); }
public async Task SendAsync_UserAgent_CorrectlyWritten() { string userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.18 Safari/537.36"; await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (var client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri); message.Headers.TryAddWithoutValidation("User-Agent", userAgent); (await client.SendAsync(message).ConfigureAwait(false)).Dispose(); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK); string agent = requestData.GetSingleHeaderValue("User-Agent"); Assert.Equal(userAgent, agent); }); }
public async Task GetAsync_ReceiveSetCookieHeader_CookieRemoved() { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = CreateHttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <HttpRequestData> serverTask = server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", $"{s_cookieName}=; Expires=Sun, 06 Nov 1994 08:49:37 GMT") }, s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(0, collection.Count); } }); }
public async Task GetAsync_SetCookieContainerAndMultipleCookieHeaders_BothCookiesSent() { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = CreateSingleCookieContainer(url); using (HttpClient client = CreateHttpClient(handler)) { var requestMessage = new HttpRequestMessage(HttpMethod.Get, url) { Version = UseVersion }; requestMessage.Headers.Add("Cookie", "A=1"); requestMessage.Headers.Add("Cookie", "B=2"); Task <HttpResponseMessage> getResponseTask = client.SendAsync(TestAsync, requestMessage); Task <HttpRequestData> serverTask = server.HandleRequestAsync(); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); HttpRequestData requestData = await serverTask; string cookieHeaderValue = GetCookieValue(requestData); #if NETFRAMEWORK // On .NET Framework multiple Cookie header values are treated as any other header values and are // concatenated using ", " as the separator. The container cookie is concatenated to // one of these values using the "; " cookie separator. var separators = new string[] { "; ", ", " }; #else var separators = new string[] { "; " }; #endif var cookieValues = cookieHeaderValue.Split(separators, StringSplitOptions.None); Assert.Contains(s_expectedCookieHeaderValue, cookieValues); Assert.Contains("A=1", cookieValues); Assert.Contains("B=2", cookieValues); Assert.Equal(3, cookieValues.Count()); } }); }
public async Task GetAsyncWithRedirect_SetCookieContainer_CorrectCookiesSent() { if (UseVersion == HttpVersion30) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/56870")] return; } const string path1 = "/foo"; const string path2 = "/bar"; const string unusedPath = "/unused"; await LoopbackServerFactory.CreateClientAndServerAsync(async url => { Uri url1 = new Uri(url, path1); Uri url2 = new Uri(url, path2); Uri unusedUrl = new Uri(url, unusedPath); HttpClientHandler handler = CreateHttpClientHandler(); handler.CookieContainer = new CookieContainer(); handler.CookieContainer.Add(url1, new Cookie("cookie1", "value1", path1)); handler.CookieContainer.Add(url2, new Cookie("cookie2", "value2", path2)); handler.CookieContainer.Add(unusedUrl, new Cookie("cookie3", "value3", unusedPath)); using (HttpClient client = CreateHttpClient(handler)) { client.DefaultRequestHeaders.ConnectionClose = true; // to avoid issues with connection pooling await client.GetAsync(url1); } }, async server => { HttpRequestData requestData1 = await server.HandleRequestAsync(HttpStatusCode.Found, new HttpHeaderData[] { new HttpHeaderData("Location", path2) }); Assert.Equal("cookie1=value1", requestData1.GetSingleHeaderValue("Cookie")); HttpRequestData requestData2 = await server.HandleRequestAsync(content: s_simpleContent); Assert.Equal("cookie2=value2", requestData2.GetSingleHeaderValue("Cookie")); }); }
public async Task PostAsync_Cancel_CancellationTokenPassedToContent(HttpContent content, CancellationTokenSource cancellationTokenSource) { if (IsWinHttpHandler) { return; } // Skipping test for a sync scenario becasue DelegateStream drops the original cancellationToken when it calls Read/Write methods. // As a result, ReadAsyncFunc receives default in cancellationToken, which will never get signaled through the cancellationTokenSource. if (!TestAsync) { return; } await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { using (var invoker = new HttpMessageInvoker(CreateHttpClientHandler())) using (var req = new HttpRequestMessage(HttpMethod.Post, uri) { Content = content, Version = UseVersion }) try { using (HttpResponseMessage resp = await invoker.SendAsync(TestAsync, req, cancellationTokenSource.Token)) { Assert.Equal("Hello World", await resp.Content.ReadAsStringAsync()); } } catch (OperationCanceledException) { } }, async server => { try { await server.HandleRequestAsync(content: "Hello World"); } catch (Exception) { } }); }
public async Task SendAsync_RequestHeaderInResponse_Success(string name, string value) { await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; HttpResponseMessage response = await client.SendAsync(TestAsync, message); Assert.Equal(value, response.Headers.GetValues(name).First()); } }, async server => { IList <HttpHeaderData> headers = new HttpHeaderData[] { new HttpHeaderData(name, value) }; HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK, headers); }); }
public async Task GetAsync_LargeHeader_Success(string headerName, int headerValueLength) { var rand = new Random(42); string headerValue = string.Concat(Enumerable.Range(0, headerValueLength).Select(_ => (char)('A' + rand.Next(26)))); const string ContentString = "hello world"; await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) using (HttpResponseMessage resp = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead)) { Assert.Equal(headerValue, resp.Headers.GetValues(headerName).Single()); Assert.Equal(ContentString, await resp.Content.ReadAsStringAsync()); } }, async server => { var headers = new List <HttpHeaderData>(); headers.Add(new HttpHeaderData(headerName, headerValue)); await server.HandleRequestAsync(HttpStatusCode.OK, headers: headers, content: ContentString); }); }
public async Task SendAsync_Cancel_CancellationTokenPropagates() { TaskCompletionSource <bool> clientCanceled = new TaskCompletionSource <bool>(); await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { var cts = new CancellationTokenSource(); cts.Cancel(); using (HttpClient client = CreateHttpClient()) { OperationCanceledException ex = null; try { await client.GetAsync(uri, cts.Token); } catch (OperationCanceledException e) { ex = e; } Assert.True(ex != null, "Expected OperationCancelledException, but no exception was thrown."); Assert.True(cts.Token.IsCancellationRequested, "cts token IsCancellationRequested"); if (!PlatformDetection.IsFullFramework) { // .NET Framework has bug where it doesn't propagate token information. Assert.True(ex.CancellationToken.IsCancellationRequested, "exception token IsCancellationRequested"); } clientCanceled.SetResult(true); } }, async server => { Task serverTask = server.HandleRequestAsync(); await clientCanceled.Task; }); }
public async Task GetAsync_AddMultipleCookieHeaders_CookiesSent() { await LoopbackServerFactory.CreateClientAndServerAsync( async uri => { using (HttpClient client = CreateHttpClient()) { var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion }; requestMessage.Headers.Add("Cookie", "A=1"); requestMessage.Headers.Add("Cookie", "B=2"); requestMessage.Headers.Add("Cookie", "C=3"); await client.SendAsync(TestAsync, requestMessage); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(); // Multiple Cookie header values are concatenated using "; " as the separator. string cookieHeaderValue = requestData.GetSingleHeaderValue("Cookie"); #if NETFRAMEWORK var separator = ", "; #else var separator = "; "; #endif var cookieValues = cookieHeaderValue.Split(new string[] { separator }, 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 GetAsync_ReceiveInvalidSetCookieHeader_ValidCookiesAdded() { if (IsNetfxHandler) { // NetfxHandler incorrectly only processes one valid cookie return; } await LoopbackServerFactory.CreateServerAsync(async (server, url) => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = new HttpClient(handler)) { Task <HttpResponseMessage> getResponseTask = client.GetAsync(url); Task <HttpRequestData> serverTask = server.HandleRequestAsync( HttpStatusCode.OK, new HttpHeaderData[] { new HttpHeaderData("Set-Cookie", "A=1; Path=/;Expires=asdfsadgads"), // invalid Expires new HttpHeaderData("Set-Cookie", "B=2; Path=/"), new HttpHeaderData("Set-Cookie", "C=3; Path=/") }, s_simpleContent); await TestHelper.WhenAllCompletedOrAnyFailed(getResponseTask, serverTask); CookieCollection collection = handler.CookieContainer.GetCookies(url); Assert.Equal(2, collection.Count); // Convert to array so we can more easily process contents, since CookieCollection does not implement IEnumerable<Cookie> Cookie[] cookies = new Cookie[3]; collection.CopyTo(cookies, 0); Assert.Contains(cookies, c => c.Name == "B" && c.Value == "2"); Assert.Contains(cookies, c => c.Name == "C" && c.Value == "3"); } }); }
[InlineData("Max-Forwards", "NotAnInteger", false)] // invalid format for header but added with TryAddWithoutValidation public async Task SendAsync_SpecialHeaderKeyOrValue_Success(string key, string value, bool parsable) { await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { bool contentHeader = false; using (HttpClient client = CreateHttpClient()) { var message = new HttpRequestMessage(HttpMethod.Get, uri) { Version = VersionFromUseHttp2 }; if (!message.Headers.TryAddWithoutValidation(key, value)) { message.Content = new StringContent(""); contentHeader = message.Content.Headers.TryAddWithoutValidation(key, value); } (await client.SendAsync(message).ConfigureAwait(false)).Dispose(); } // Validate our test by validating our understanding of a header's parsability. HttpHeaders headers = contentHeader ? (HttpHeaders) new StringContent("").Headers : new HttpRequestMessage().Headers; if (parsable) { headers.Add(key, value); } else { Assert.Throws <FormatException>(() => headers.Add(key, value)); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK); Assert.Equal(value, requestData.GetSingleHeaderValue(key)); }); }
public async Task UnreadResponseMessage_Collectible() { await LoopbackServerFactory.CreateServerAsync(async (server, url) => { using (HttpClient client = CreateHttpClient()) { Func <Task <WeakReference> > getAsync = () => client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ContinueWith(t => new WeakReference(t.Result)); Task <WeakReference> wrt = getAsync(); await server.HandleRequestAsync(content: new string('a', 16 * 1024)); 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 Dispose_HandlerWithProxy_ProxyNotDisposed() { var proxy = new TrackDisposalProxy(); await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClientHandler handler = CreateHttpClientHandler()) { handler.UseProxy = true; handler.Proxy = proxy; using (HttpClient client = CreateHttpClient(handler)) { Assert.Equal("hello", await client.GetStringAsync(uri)); } } }, async server => { await server.HandleRequestAsync(content: "hello"); }); Assert.True(proxy.ProxyUsed); Assert.False(proxy.Disposed); }
public async Task GetAsync_EmptyResponseHeader_Success() { IList <HttpHeaderData> headers = new HttpHeaderData[] { new HttpHeaderData("x-test", "SendAsync_EmptyHeader_Success"), new HttpHeaderData("x-empty", ""), new HttpHeaderData("x-last", "bye") }; await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { using (HttpClient client = CreateHttpClient()) { HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false); // HTTP/1.1 LoopbackServer adds Connection: close and Date to responses. Assert.Equal(UseHttp2LoopbackServer ? headers.Count : headers.Count + 2, response.Headers.Count()); Assert.NotNull(response.Headers.GetValues("x-empty")); } }, async server => { HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK, headers); }); }
public async Task SendAsync_InvalidHeader_Throw(string value) { await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { HttpClientHandler handler = CreateHttpClientHandler(); using (HttpClient client = CreateHttpClient()) { var request = new HttpRequestMessage(HttpMethod.Get, uri); Assert.True(request.Headers.TryAddWithoutValidation("bad", value)); await Assert.ThrowsAsync <HttpRequestException>(() => client.SendAsync(request)); } }, async server => { try { // Client should abort at some point so this is going to throw. HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK).ConfigureAwait(false); } catch (IOException) { }; }); }
public async Task IncompleteResponseStream_ResponseDropped_CancelsRequestToServer() { if (UseVersion == HttpVersion30) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/58234")] return; } using (HttpClient client = CreateHttpClient()) { bool stopGCs = false; await LoopbackServerFactory.CreateClientAndServerAsync(async url => { await GetAndDropResponse(client, url); while (!Volatile.Read(ref stopGCs)) { await Task.Delay(10); GC.Collect(); GC.WaitForPendingFinalizers(); } }, server => server.AcceptConnectionAsync(async connection => { try { HttpRequestData data = await connection.ReadRequestDataAsync(readBody: false); await connection.SendResponseHeadersAsync(headers: new HttpHeaderData[] { new HttpHeaderData("SomeHeaderName", "AndValue") }); await connection.WaitForCancellationAsync(); } finally { Volatile.Write(ref stopGCs, true); } })); } }