public Task ExpectedKeysAreInFeatures() { var handler = new ClientHandler(new PathString("/A/Path/"), new InspectingApplication(features => { // TODO: Assert.True(context.RequestAborted.CanBeCanceled); Assert.Equal("HTTP/1.1", features.Get <IHttpRequestFeature>().Protocol); Assert.Equal("GET", features.Get <IHttpRequestFeature>().Method); Assert.Equal("https", features.Get <IHttpRequestFeature>().Scheme); Assert.Equal("/A/Path", features.Get <IHttpRequestFeature>().PathBase); Assert.Equal("/and/file.txt", features.Get <IHttpRequestFeature>().Path); Assert.Equal("?and=query", features.Get <IHttpRequestFeature>().QueryString); Assert.NotNull(features.Get <IHttpRequestFeature>().Body); Assert.NotNull(features.Get <IHttpRequestFeature>().Headers); Assert.NotNull(features.Get <IHttpResponseFeature>().Headers); Assert.NotNull(features.Get <IHttpResponseFeature>().Body); Assert.Equal(200, features.Get <IHttpResponseFeature>().StatusCode); Assert.Null(features.Get <IHttpResponseFeature>().ReasonPhrase); Assert.Equal("example.com", features.Get <IHttpRequestFeature>().Headers["host"]); Assert.NotNull(features.Get <IHttpRequestLifetimeFeature>()); })); var httpClient = new HttpClient(handler); return(httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query")); }
public async Task ResubmitRequestWorks() { int requestCount = 1; var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => { int read = await context.Request.Body.ReadAsync(new byte[100], 0, 100); Assert.Equal(11, read); context.Response.Headers["TestHeader"] = "TestValue:" + requestCount++; })); HttpMessageInvoker invoker = new HttpMessageInvoker(handler); HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, "https://example.com/"); message.Content = new StringContent("Hello World"); HttpResponseMessage response = await invoker.SendAsync(message, CancellationToken.None); Assert.Equal("TestValue:1", response.Headers.GetValues("TestHeader").First()); response = await invoker.SendAsync(message, CancellationToken.None); Assert.Equal("TestValue:2", response.Headers.GetValues("TestHeader").First()); }
public Task ExceptionFromOnStartingWithErrorHandlerIsReported() { var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => { context.Response.OnStarting(() => { throw new InvalidOperationException(new string('a', 1024 * 32)); }); try { await context.Response.WriteAsync("Hello World"); } catch (Exception ex) { // This is no longer the first write, so it doesn't trigger OnStarting again. // The exception is large enough that it fills the pipe and stalls. await context.Response.WriteAsync(ex.ToString()); } })); var httpClient = new HttpClient(handler); return(Assert.ThrowsAsync <InvalidOperationException>(() => httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead))); }
public async Task ClientDisposalCloses() { var block = new TaskCompletionSource <int>(TaskCreationOptions.RunContinuationsAsynchronously); var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => { context.Response.Headers["TestHeader"] = "TestValue"; await context.Response.Body.FlushAsync(); await block.Task; })); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead); Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First()); Stream responseStream = await response.Content.ReadAsStreamAsync(); Task <int> readTask = responseStream.ReadAsync(new byte[100], 0, 100); Assert.False(readTask.IsCompleted); responseStream.Dispose(); await Assert.ThrowsAsync <OperationCanceledException>(() => readTask.DefaultTimeout()); block.SetResult(0); }
public async Task ServerTrailersSetOnResponseAfterContentRead() { var tcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => { context.Response.AppendTrailer("StartTrailer", "Value!"); await context.Response.WriteAsync("Hello World"); await context.Response.Body.FlushAsync(); // Pause writing response to ensure trailers are written at the end await tcs.Task; await context.Response.WriteAsync("Bye World"); await context.Response.Body.FlushAsync(); context.Response.AppendTrailer("EndTrailer", "Value!"); })); var invoker = new HttpMessageInvoker(handler); var message = new HttpRequestMessage(HttpMethod.Post, "https://example.com/"); var response = await invoker.SendAsync(message, CancellationToken.None); Assert.Empty(response.TrailingHeaders); var responseBody = await response.Content.ReadAsStreamAsync(); int read = await responseBody.ReadAsync(new byte[100], 0, 100); Assert.Equal(11, read); Assert.Empty(response.TrailingHeaders); var readTask = responseBody.ReadAsync(new byte[100], 0, 100); Assert.False(readTask.IsCompleted); tcs.TrySetResult(null); read = await readTask; Assert.Equal(9, read); Assert.Empty(response.TrailingHeaders); // Read nothing because we're at the end of the response read = await responseBody.ReadAsync(new byte[100], 0, 100); Assert.Equal(0, read); // Ensure additional reads after end don't effect trailers read = await responseBody.ReadAsync(new byte[100], 0, 100); Assert.Equal(0, read); Assert.Collection(response.TrailingHeaders, kvp => { Assert.Equal("StartTrailer", kvp.Key); Assert.Equal("Value!", kvp.Value.Single()); }, kvp => { Assert.Equal("EndTrailer", kvp.Key); Assert.Equal("Value!", kvp.Value.Single()); }); }