Skip to content

Commit

Permalink
add response / request streaming test
Browse files Browse the repository at this point in the history
  • Loading branch information
campersau committed Aug 30, 2023
1 parent 92ae132 commit 487ef33
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
67 changes: 61 additions & 6 deletions src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,59 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders

#if NETCOREAPP

[OuterLoop]
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))]
public async Task BrowserHttpHandler_Streaming()
{
var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingRequest");
var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingResponse");

var req = new HttpRequestMessage(HttpMethod.Post, Configuration.Http.RemoteHttp2Server.BaseUri + "echobody.ashx");

req.Options.Set(WebAssemblyEnableStreamingRequestKey, true);
req.Options.Set(WebAssemblyEnableStreamingResponseKey, true);

byte[] body = new byte[1024 * 1024];
Random.Shared.NextBytes(body);

int readOffset = 0;
req.Content = new StreamContent(new DelegateStream(
readAsyncFunc: async (buffer, offset, count, cancellationToken) =>
{
await Task.Delay(1);
if (readOffset < body.Length)
{
int send = Math.Min(body.Length - readOffset, count);
body.AsSpan(readOffset, send).CopyTo(buffer.AsSpan(offset, send));
readOffset += send;
return send;
}
return 0;
}));

using (HttpClient client = CreateHttpClientForRemoteServer(Configuration.Http.RemoteHttp2Server))
using (HttpResponseMessage response = await client.SendAsync(req))
{
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Streaming requests can't set Content-Length
Assert.False(response.Headers.Contains("X-HttpRequest-Headers-ContentLength"));
// Streaming response uses StreamContent
Assert.Equal(typeof(StreamContent), response.Content.GetType());

var stream = await response.Content.ReadAsStreamAsync();
var buffer = new byte[1024 * 1024];
int totalCount = 0;
int fetchedCount = 0;
do
{
fetchedCount = await stream.ReadAsync(buffer, 0, buffer.Length);
Assert.True(body.AsSpan(totalCount, fetchedCount).SequenceEqual(buffer.AsSpan(0, fetchedCount)));
totalCount += fetchedCount;
} while (fetchedCount != 0);
Assert.Equal(body.Length, totalCount);
}
}

[OuterLoop]
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))]
[InlineData(true)]
Expand All @@ -242,17 +295,17 @@ public async Task BrowserHttpHandler_StreamingRequest(bool useStringContent)

req.Options.Set(WebAssemblyEnableStreamingRequestKey, true);

int expectedBodyLength;
int size;
if (useStringContent)
{
string bodyContent = "Hello World";
expectedBodyLength = bodyContent.Length;
size = bodyContent.Length;
req.Content = new StringContent(bodyContent);
}
else
{
expectedBodyLength = 1500 * 1024 * 1024;
int remaining = expectedBodyLength;
size = 1500 * 1024 * 1024;
int remaining = size;
req.Content = new StreamContent(new DelegateStream(
readAsyncFunc: (buffer, offset, count, cancellationToken) =>
{
Expand All @@ -273,11 +326,12 @@ public async Task BrowserHttpHandler_StreamingRequest(bool useStringContent)
using (HttpResponseMessage response = await client.SendAsync(req))
{
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(expectedBodyLength.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Body-Length")));
Assert.Equal(size.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Body-Length")));
// Streaming requests can't set Content-Length
Assert.Equal(useStringContent, response.Headers.Contains("X-HttpRequest-Headers-ContentLength"));
if (useStringContent)
{
Assert.Equal(expectedBodyLength.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Headers-ContentLength")));
Assert.Equal(size.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Headers-ContentLength")));
}
}
}
Expand Down Expand Up @@ -327,6 +381,7 @@ public async Task BrowserHttpHandler_StreamingResponse()
// we need to switch off Response buffering of default ResponseContentRead option
using (HttpResponseMessage response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead))
{
// Streaming response uses StreamContent
Assert.Equal(typeof(StreamContent), response.Content.GetType());

Assert.Equal("application/octet-stream", response.Content.Headers.ContentType.MediaType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public async Task Invoke(HttpContext context)
await LargeResponseHandler.InvokeAsync(context);
return;
}
if (path.Equals(new PathString("/echobody.ashx")))
{
await EchoBodyHandler.InvokeAsync(context);
return;
}

// Default handling.
await EchoHandler.InvokeAsync(context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;

namespace NetCoreServer
{
public class EchoBodyHandler
{
public static async Task InvokeAsync(HttpContext context)
{
context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = null;

// Report back original request method verb.
context.Response.Headers["X-HttpRequest-Method"] = context.Request.Method;

// Report back original entity-body related request headers.
string contentLength = context.Request.Headers["Content-Length"];
if (!string.IsNullOrEmpty(contentLength))
{
context.Response.Headers["X-HttpRequest-Headers-ContentLength"] = contentLength;
}

string transferEncoding = context.Request.Headers["Transfer-Encoding"];
if (!string.IsNullOrEmpty(transferEncoding))
{
context.Response.Headers["X-HttpRequest-Headers-TransferEncoding"] = transferEncoding;
}

context.Response.StatusCode = 200;
context.Response.ContentType = context.Request.ContentType;
await context.Request.Body.CopyToAsync(context.Response.Body);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<ItemGroup>
<Compile Include="Handlers\DeflateHandler.cs" />
<Compile Include="Handlers\EchoHandler.cs" />
<Compile Include="Handlers\EchoBodyHandler.cs" />
<Compile Include="Handlers\EchoWebSocketHandler.cs" />
<Compile Include="Handlers\EchoWebSocketHeadersHandler.cs" />
<Compile Include="Handlers\EmptyContentHandler.cs" />
Expand Down

0 comments on commit 487ef33

Please sign in to comment.