Skip to content

Commit 487ef33

Browse files
committed
add response / request streaming test
1 parent 92ae132 commit 487ef33

File tree

4 files changed

+105
-6
lines changed

4 files changed

+105
-6
lines changed

src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,59 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders
230230

231231
#if NETCOREAPP
232232

233+
[OuterLoop]
234+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))]
235+
public async Task BrowserHttpHandler_Streaming()
236+
{
237+
var WebAssemblyEnableStreamingRequestKey = new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingRequest");
238+
var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey<bool>("WebAssemblyEnableStreamingResponse");
239+
240+
var req = new HttpRequestMessage(HttpMethod.Post, Configuration.Http.RemoteHttp2Server.BaseUri + "echobody.ashx");
241+
242+
req.Options.Set(WebAssemblyEnableStreamingRequestKey, true);
243+
req.Options.Set(WebAssemblyEnableStreamingResponseKey, true);
244+
245+
byte[] body = new byte[1024 * 1024];
246+
Random.Shared.NextBytes(body);
247+
248+
int readOffset = 0;
249+
req.Content = new StreamContent(new DelegateStream(
250+
readAsyncFunc: async (buffer, offset, count, cancellationToken) =>
251+
{
252+
await Task.Delay(1);
253+
if (readOffset < body.Length)
254+
{
255+
int send = Math.Min(body.Length - readOffset, count);
256+
body.AsSpan(readOffset, send).CopyTo(buffer.AsSpan(offset, send));
257+
readOffset += send;
258+
return send;
259+
}
260+
return 0;
261+
}));
262+
263+
using (HttpClient client = CreateHttpClientForRemoteServer(Configuration.Http.RemoteHttp2Server))
264+
using (HttpResponseMessage response = await client.SendAsync(req))
265+
{
266+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
267+
// Streaming requests can't set Content-Length
268+
Assert.False(response.Headers.Contains("X-HttpRequest-Headers-ContentLength"));
269+
// Streaming response uses StreamContent
270+
Assert.Equal(typeof(StreamContent), response.Content.GetType());
271+
272+
var stream = await response.Content.ReadAsStreamAsync();
273+
var buffer = new byte[1024 * 1024];
274+
int totalCount = 0;
275+
int fetchedCount = 0;
276+
do
277+
{
278+
fetchedCount = await stream.ReadAsync(buffer, 0, buffer.Length);
279+
Assert.True(body.AsSpan(totalCount, fetchedCount).SequenceEqual(buffer.AsSpan(0, fetchedCount)));
280+
totalCount += fetchedCount;
281+
} while (fetchedCount != 0);
282+
Assert.Equal(body.Length, totalCount);
283+
}
284+
}
285+
233286
[OuterLoop]
234287
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))]
235288
[InlineData(true)]
@@ -242,17 +295,17 @@ public async Task BrowserHttpHandler_StreamingRequest(bool useStringContent)
242295

243296
req.Options.Set(WebAssemblyEnableStreamingRequestKey, true);
244297

245-
int expectedBodyLength;
298+
int size;
246299
if (useStringContent)
247300
{
248301
string bodyContent = "Hello World";
249-
expectedBodyLength = bodyContent.Length;
302+
size = bodyContent.Length;
250303
req.Content = new StringContent(bodyContent);
251304
}
252305
else
253306
{
254-
expectedBodyLength = 1500 * 1024 * 1024;
255-
int remaining = expectedBodyLength;
307+
size = 1500 * 1024 * 1024;
308+
int remaining = size;
256309
req.Content = new StreamContent(new DelegateStream(
257310
readAsyncFunc: (buffer, offset, count, cancellationToken) =>
258311
{
@@ -273,11 +326,12 @@ public async Task BrowserHttpHandler_StreamingRequest(bool useStringContent)
273326
using (HttpResponseMessage response = await client.SendAsync(req))
274327
{
275328
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
276-
Assert.Equal(expectedBodyLength.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Body-Length")));
329+
Assert.Equal(size.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Body-Length")));
330+
// Streaming requests can't set Content-Length
277331
Assert.Equal(useStringContent, response.Headers.Contains("X-HttpRequest-Headers-ContentLength"));
278332
if (useStringContent)
279333
{
280-
Assert.Equal(expectedBodyLength.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Headers-ContentLength")));
334+
Assert.Equal(size.ToString(), Assert.Single(response.Headers.GetValues("X-HttpRequest-Headers-ContentLength")));
281335
}
282336
}
283337
}
@@ -327,6 +381,7 @@ public async Task BrowserHttpHandler_StreamingResponse()
327381
// we need to switch off Response buffering of default ResponseContentRead option
328382
using (HttpResponseMessage response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead))
329383
{
384+
// Streaming response uses StreamContent
330385
Assert.Equal(typeof(StreamContent), response.Content.GetType());
331386

332387
Assert.Equal("application/octet-stream", response.Content.Headers.ContentType.MediaType);

src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/GenericHandler.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ public async Task Invoke(HttpContext context)
8888
await LargeResponseHandler.InvokeAsync(context);
8989
return;
9090
}
91+
if (path.Equals(new PathString("/echobody.ashx")))
92+
{
93+
await EchoBodyHandler.InvokeAsync(context);
94+
return;
95+
}
9196

9297
// Default handling.
9398
await EchoHandler.InvokeAsync(context);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore.Http;
7+
using Microsoft.AspNetCore.Http.Features;
8+
9+
namespace NetCoreServer
10+
{
11+
public class EchoBodyHandler
12+
{
13+
public static async Task InvokeAsync(HttpContext context)
14+
{
15+
context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = null;
16+
17+
// Report back original request method verb.
18+
context.Response.Headers["X-HttpRequest-Method"] = context.Request.Method;
19+
20+
// Report back original entity-body related request headers.
21+
string contentLength = context.Request.Headers["Content-Length"];
22+
if (!string.IsNullOrEmpty(contentLength))
23+
{
24+
context.Response.Headers["X-HttpRequest-Headers-ContentLength"] = contentLength;
25+
}
26+
27+
string transferEncoding = context.Request.Headers["Transfer-Encoding"];
28+
if (!string.IsNullOrEmpty(transferEncoding))
29+
{
30+
context.Response.Headers["X-HttpRequest-Headers-TransferEncoding"] = transferEncoding;
31+
}
32+
33+
context.Response.StatusCode = 200;
34+
context.Response.ContentType = context.Request.ContentType;
35+
await context.Request.Body.CopyToAsync(context.Response.Body);
36+
}
37+
}
38+
}

src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/NetCoreServer.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<ItemGroup>
2727
<Compile Include="Handlers\DeflateHandler.cs" />
2828
<Compile Include="Handlers\EchoHandler.cs" />
29+
<Compile Include="Handlers\EchoBodyHandler.cs" />
2930
<Compile Include="Handlers\EchoWebSocketHandler.cs" />
3031
<Compile Include="Handlers\EchoWebSocketHeadersHandler.cs" />
3132
<Compile Include="Handlers\EmptyContentHandler.cs" />

0 commit comments

Comments
 (0)