#366 Add flag to disable synchronous IO
This commit is contained in:
parent
ac4157c627
commit
13b867a90e
|
|
@ -29,7 +29,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
IHttpAuthenticationFeature,
|
||||
IHttpUpgradeFeature,
|
||||
IHttpRequestIdentifierFeature,
|
||||
IHttpMaxRequestBodySizeFeature
|
||||
IHttpMaxRequestBodySizeFeature,
|
||||
IHttpBodyControlFeature
|
||||
{
|
||||
private RequestContext _requestContext;
|
||||
private IFeatureCollection _features;
|
||||
|
|
@ -464,6 +465,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
}
|
||||
}
|
||||
|
||||
bool IHttpBodyControlFeature.AllowSynchronousIO
|
||||
{
|
||||
get => _requestContext.AllowSynchronousIO;
|
||||
set => _requestContext.AllowSynchronousIO = value;
|
||||
}
|
||||
|
||||
bool IHttpMaxRequestBodySizeFeature.IsReadOnly => Request.HasRequestBodyStarted;
|
||||
|
||||
long? IHttpMaxRequestBodySizeFeature.MaxRequestBodySize
|
||||
|
|
|
|||
|
|
@ -131,6 +131,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that controls whether synchronous IO is allowed for the HttpContext.Request.Body and HttpContext.Response.Body.
|
||||
/// The default is `true`.
|
||||
/// </summary>
|
||||
public bool AllowSynchronousIO { get; set; } = true;
|
||||
|
||||
internal void Apply(UrlGroup urlGroup, RequestQueue requestQueue)
|
||||
{
|
||||
_urlGroup = urlGroup;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
// private byte[] _referredTokenBindingId;
|
||||
|
||||
private BoundaryType _contentBoundaryType;
|
||||
|
||||
private long? _contentLength;
|
||||
private RequestStream _nativeStream;
|
||||
|
||||
|
|
@ -149,10 +150,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
if (_nativeStream == null && HasEntityBody)
|
||||
{
|
||||
_nativeStream = new RequestStream(RequestContext)
|
||||
{
|
||||
MaxSize = RequestContext.Server.Options.MaxRequestBodySize
|
||||
};
|
||||
_nativeStream = new RequestStream(RequestContext);
|
||||
}
|
||||
return _nativeStream;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
_memoryBlob = memoryBlob;
|
||||
Request = new Request(this, _memoryBlob);
|
||||
Response = new Response(this);
|
||||
AllowSynchronousIO = server.Options.AllowSynchronousIO;
|
||||
}
|
||||
|
||||
internal HttpSysListener Server { get; }
|
||||
|
|
@ -88,6 +89,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
public bool IsUpgradableRequest => Request.IsUpgradable;
|
||||
|
||||
internal bool AllowSynchronousIO { get; set; }
|
||||
|
||||
public Task<Stream> UpgradeAsync()
|
||||
{
|
||||
if (!IsUpgradableRequest)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
internal RequestStream(RequestContext httpContext)
|
||||
{
|
||||
_requestContext = httpContext;
|
||||
_maxSize = _requestContext.Server.Options.MaxRequestBodySize;
|
||||
}
|
||||
|
||||
internal RequestContext RequestContext
|
||||
|
|
@ -111,6 +112,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
public override unsafe int Read([In, Out] byte[] buffer, int offset, int size)
|
||||
{
|
||||
if (!RequestContext.AllowSynchronousIO)
|
||||
{
|
||||
throw new InvalidOperationException("Synchronous IO APIs are disabled, see AllowSynchronousIO.");
|
||||
}
|
||||
|
||||
ValidateReadBuffer(buffer, offset, size);
|
||||
CheckSizeLimit();
|
||||
if (_closed)
|
||||
|
|
|
|||
|
|
@ -91,10 +91,16 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
// Send headers
|
||||
public override void Flush()
|
||||
{
|
||||
if (!RequestContext.AllowSynchronousIO)
|
||||
{
|
||||
throw new InvalidOperationException("Synchronous IO APIs are disabled, see AllowSynchronousIO.");
|
||||
}
|
||||
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FlushInternal(endOfRequest: false);
|
||||
}
|
||||
|
||||
|
|
@ -449,9 +455,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (!RequestContext.AllowSynchronousIO)
|
||||
{
|
||||
throw new InvalidOperationException("Synchronous IO APIs are disabled, see AllowSynchronousIO.");
|
||||
}
|
||||
|
||||
// Validates for null and bounds. Allows count == 0.
|
||||
// TODO: Verbose log parameters
|
||||
var data = new ArraySegment<byte>(buffer, offset, count);
|
||||
|
||||
CheckDisposed();
|
||||
|
||||
CheckWriteCount(count);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{ typeof(IHttpRequestIdentifierFeature), _identityFunc },
|
||||
{ typeof(RequestContext), ctx => ctx.RequestContext },
|
||||
{ typeof(IHttpMaxRequestBodySizeFeature), _identityFunc },
|
||||
{ typeof(IHttpBodyControlFeature), _identityFunc },
|
||||
};
|
||||
|
||||
private readonly FeatureContext _featureContext;
|
||||
|
|
|
|||
|
|
@ -60,10 +60,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
string input = new StreamReader(context.Request.Body).ReadToEnd();
|
||||
Assert.Equal("Hello World", input);
|
||||
context.Response.ContentLength = 11;
|
||||
using (var writer = new StreamWriter(context.Response.Body))
|
||||
{
|
||||
writer.Write("Hello World");
|
||||
}
|
||||
var writer = new StreamWriter(context.Response.Body);
|
||||
await writer.WriteAsync("Hello World");
|
||||
await writer.FlushAsync();
|
||||
|
||||
string response = await responseTask;
|
||||
Assert.Equal("Hello World", response);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
byte[] body = Encoding.UTF8.GetBytes("Hello World");
|
||||
context.Response.Body.Write(body, 0, body.Length);
|
||||
await context.Response.Body.WriteAsync(body, 0, body.Length);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.Headers["Upgrade"] = "WebSocket"); // Win8.1 blocks anything but WebSocket
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.UpgradeAsync());
|
||||
|
|
|
|||
|
|
@ -16,6 +16,32 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
public class RequestBodyTests
|
||||
{
|
||||
[ConditionalFact]
|
||||
public async Task RequestBody_SyncReadEnabledByDefault_ThrowsWhenDisabled()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<string> responseTask = SendRequestAsync(address, "Hello World");
|
||||
|
||||
Assert.True(server.Options.AllowSynchronousIO);
|
||||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
byte[] input = new byte[100];
|
||||
|
||||
Assert.True(context.AllowSynchronousIO);
|
||||
var read = context.Request.Body.Read(input, 0, input.Length);
|
||||
context.Response.ContentLength = read;
|
||||
context.Response.Body.Write(input, 0, read);
|
||||
|
||||
context.AllowSynchronousIO = false;
|
||||
Assert.Throws<InvalidOperationException>(() => context.Request.Body.Read(input, 0, input.Length));
|
||||
|
||||
string response = await responseTask;
|
||||
Assert.Equal("Hello World", response);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task RequestBody_ReadSync_Success()
|
||||
{
|
||||
|
|
@ -24,6 +50,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
Task<string> responseTask = SendRequestAsync(address, "Hello World");
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
byte[] input = new byte[100];
|
||||
int read = context.Request.Body.Read(input, 0, input.Length);
|
||||
|
|
@ -81,6 +108,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
Task<string> responseTask = SendRequestAsync(address, "Hello World");
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
byte[] input = new byte[100];
|
||||
Assert.Throws<ArgumentNullException>("buffer", () => context.Request.Body.Read(null, 0, 1));
|
||||
|
|
@ -106,6 +134,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
Task<string> responseTask = SendRequestAsync(address, content);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
byte[] input = new byte[10];
|
||||
int read = context.Request.Body.Read(input, 0, input.Length);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,41 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
public class ResponseBodyTests
|
||||
{
|
||||
[ConditionalFact]
|
||||
public async Task ResponseBody_SyncWriteEnabledByDefault_ThrowsWhenDisabled()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
|
||||
Assert.True(context.AllowSynchronousIO);
|
||||
|
||||
context.Response.Body.Flush();
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
context.Response.Body.Flush();
|
||||
|
||||
context.AllowSynchronousIO = false;
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Flush());
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[10], 0, 10));
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Flush());
|
||||
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
context.Dispose();
|
||||
|
||||
var response = await responseTask;
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
IEnumerable<string> ignored;
|
||||
Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length");
|
||||
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
||||
Assert.Equal(new byte[20], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task ResponseBody_WriteNoHeaders_DefaultsToChunked()
|
||||
{
|
||||
|
|
@ -24,6 +59,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
|
|
@ -45,6 +81,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
|
|
@ -95,6 +132,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.Headers["Content-lenGth"] = " 30 ";
|
||||
var stream = context.Response.Body;
|
||||
|
|
@ -181,6 +219,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.Headers["Content-lenGth"] = " 10 ";
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
|
|
@ -206,6 +245,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.Body.Write(new byte[10], 0, 0);
|
||||
Assert.True(context.Response.HasStarted);
|
||||
|
|
@ -380,6 +420,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
server.Options.ThrowWriteExceptions = true;
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var cts = new CancellationTokenSource();
|
||||
var responseTask = SendRequestAsync(address, cts.Token);
|
||||
|
||||
|
|
@ -444,6 +485,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
var cts = new CancellationTokenSource();
|
||||
var responseTask = SendRequestAsync(address, cts.Token);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
// First write sends headers
|
||||
cts.Cancel();
|
||||
|
|
@ -555,6 +597,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
RequestContext context;
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
context.Response.ContentLength = 10;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
// Http.Sys will add this for us
|
||||
Assert.Null(context.Response.ContentLength);
|
||||
context.Dispose();
|
||||
|
|
@ -381,6 +381,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
var responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.Headers["x-request-count"] = "1";
|
||||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
|
|
@ -418,8 +419,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["x-request-count"] = "1";
|
||||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
context.Response.Body.Flush();
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
await context.Response.Body.FlushAsync();
|
||||
context.Dispose();
|
||||
|
||||
var response = await responseTask;
|
||||
|
|
@ -453,7 +454,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
context.Response.ContentLength = 10;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[10], 0, 10);
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
// Http.Sys will add this for us
|
||||
Assert.Null(context.Response.ContentLength);
|
||||
context.Dispose();
|
||||
|
|
@ -999,7 +1000,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-range"] = "bytes 0-10/100";
|
||||
context.Response.ContentLength = 11;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[100], 0, 11);
|
||||
await context.Response.Body.WriteAsync(new byte[100], 0, 11);
|
||||
context.Dispose();
|
||||
|
||||
var response = await responseTask;
|
||||
|
|
@ -1016,7 +1017,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-range"] = "bytes 0-10/100";
|
||||
context.Response.ContentLength = 11;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[100], 0, 11);
|
||||
await context.Response.Body.WriteAsync(new byte[100], 0, 11);
|
||||
context.Dispose();
|
||||
|
||||
response = await responseTask;
|
||||
|
|
@ -1041,7 +1042,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
context.Response.ContentLength = 100;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[100], 0, 100);
|
||||
await context.Response.Body.WriteAsync(new byte[100], 0, 100);
|
||||
context.Dispose();
|
||||
|
||||
var response = await responseTask;
|
||||
|
|
@ -1071,7 +1072,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
|
||||
context.Response.ContentLength = 100;
|
||||
context.Response.CacheTtl = TimeSpan.FromSeconds(10);
|
||||
context.Response.Body.Write(new byte[100], 0, 100);
|
||||
await context.Response.Body.WriteAsync(new byte[100], 0, 100);
|
||||
context.Dispose();
|
||||
|
||||
var response = await responseTask;
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
{
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
server.Options.AllowSynchronousIO = true;
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
var responseHeaders = context.Response.Headers;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,10 +42,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
context.Response.ContentLength = 11;
|
||||
using (var writer = new StreamWriter(context.Response.Body))
|
||||
{
|
||||
writer.Write("Hello World");
|
||||
}
|
||||
var writer = new StreamWriter(context.Response.Body);
|
||||
await writer.WriteAsync("Hello World");
|
||||
await writer.FlushAsync();
|
||||
|
||||
string response = await responseTask;
|
||||
Assert.Equal("Hello World", response);
|
||||
|
|
@ -61,13 +60,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
var responseTask = SendRequestAsync(address, "Hello World");
|
||||
|
||||
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
|
||||
string input = new StreamReader(context.Request.Body).ReadToEnd();
|
||||
var input = await new StreamReader(context.Request.Body).ReadToEndAsync();
|
||||
Assert.Equal("Hello World", input);
|
||||
context.Response.ContentLength = 11;
|
||||
using (var writer = new StreamWriter(context.Response.Body))
|
||||
{
|
||||
writer.Write("Hello World");
|
||||
}
|
||||
var writer = new StreamWriter(context.Response.Body);
|
||||
await writer.WriteAsync("Hello World");
|
||||
await writer.FlushAsync();
|
||||
|
||||
var response = await responseTask;
|
||||
Assert.Equal("Hello World", response);
|
||||
|
|
@ -218,10 +216,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
context.Response.Headers["Connection"] = "close";
|
||||
|
||||
context.Response.ContentLength = 11;
|
||||
using (var writer = new StreamWriter(context.Response.Body))
|
||||
{
|
||||
writer.Write("Hello World");
|
||||
}
|
||||
var writer = new StreamWriter(context.Response.Body);
|
||||
await writer.WriteAsync("Hello World");
|
||||
await writer.FlushAsync();
|
||||
|
||||
Assert.True(canceled.WaitOne(interval), "Disconnected");
|
||||
Assert.True(ct.IsCancellationRequested, "IsCancellationRequested");
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
Assert.True(feature.IsReadOnly);
|
||||
Assert.Null(feature.MaxRequestBodySize);
|
||||
Assert.Throws<InvalidOperationException>(() => feature.MaxRequestBodySize = 12);
|
||||
Assert.Equal(15, stream.Read(new byte[15], 0, 15));
|
||||
Assert.Equal(15, await stream.ReadAsync(new byte[15], 0, 15));
|
||||
upgraded = true;
|
||||
waitHandle.Set();
|
||||
}))
|
||||
|
|
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
using (Stream stream = await SendOpaqueRequestAsync("GET", address))
|
||||
{
|
||||
stream.Write(new byte[15], 0, 15);
|
||||
Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out");
|
||||
Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(10)), "Timed out");
|
||||
Assert.True(upgraded.HasValue, "Upgraded not set");
|
||||
Assert.True(upgraded.Value, "Upgrade failed");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, options => options.MaxRequestBodySize = 11, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var feature = httpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(feature.IsReadOnly);
|
||||
|
|
@ -86,6 +87,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, options => options.MaxRequestBodySize = 11, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var feature = httpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(feature.IsReadOnly);
|
||||
|
|
@ -151,6 +153,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, options => options.MaxRequestBodySize = 10, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var feature = httpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(feature.IsReadOnly);
|
||||
|
|
@ -220,6 +223,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, options => options.MaxRequestBodySize = 10, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var feature = httpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(feature.IsReadOnly);
|
||||
|
|
@ -290,6 +294,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, options => options.MaxRequestBodySize = 10, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var feature = httpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
Assert.NotNull(feature);
|
||||
Assert.False(feature.IsReadOnly);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Net.Sockets;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
byte[] input = new byte[100];
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
int read = httpContext.Request.Body.Read(input, 0, input.Length);
|
||||
httpContext.Response.ContentLength = read;
|
||||
httpContext.Response.Body.Write(input, 0, read);
|
||||
|
|
@ -75,6 +77,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
byte[] input = new byte[100];
|
||||
Assert.Throws<ArgumentNullException>("buffer", () => httpContext.Request.Body.Read(null, 0, 1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>("offset", () => httpContext.Request.Body.Read(input, -1, 1));
|
||||
|
|
@ -99,6 +102,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
byte[] input = new byte[10];
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
int read = httpContext.Request.Body.Read(input, 0, input.Length);
|
||||
Assert.Equal(5, read);
|
||||
content.Block.Release();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Net.Http;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -22,6 +23,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
httpContext.Response.Body.Write(new byte[10], 0, 10);
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
|
|
@ -42,6 +44,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
httpContext.Response.Body.Write(new byte[10], 0, 10);
|
||||
await httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
await httpContext.Response.Body.FlushAsync();
|
||||
|
|
@ -85,6 +88,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
httpContext.Response.Headers["Content-lenGth"] = " 30 ";
|
||||
Stream stream = httpContext.Response.Body;
|
||||
stream.EndWrite(stream.BeginWrite(new byte[10], 0, 10, null, null));
|
||||
|
|
@ -124,8 +128,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Response.Headers["Content-lenGth"] = " 20 ";
|
||||
httpContext.Response.Body.Write(new byte[5], 0, 5);
|
||||
return Task.FromResult(0);
|
||||
return httpContext.Response.Body.WriteAsync(new byte[5], 0, 5);
|
||||
}))
|
||||
{
|
||||
Assert.Throws<AggregateException>(() => SendRequestAsync(address).Result);
|
||||
|
|
@ -137,13 +140,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
var completed = false;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Response.Headers["Content-lenGth"] = " 10 ";
|
||||
httpContext.Response.Body.Write(new byte[5], 0, 5);
|
||||
Assert.Throws<InvalidOperationException>(() => httpContext.Response.Body.Write(new byte[6], 0, 6));
|
||||
await httpContext.Response.Body.WriteAsync(new byte[5], 0, 5);
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() =>
|
||||
httpContext.Response.Body.WriteAsync(new byte[6], 0, 6));
|
||||
completed = true;
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
await Assert.ThrowsAsync<HttpRequestException>(() => SendRequestAsync(address));
|
||||
|
|
@ -161,6 +164,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
try
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
httpContext.Response.Headers["Content-lenGth"] = " 10 ";
|
||||
httpContext.Response.Body.Write(new byte[10], 0, 10);
|
||||
httpContext.Response.Body.Write(new byte[9], 0, 9);
|
||||
|
|
@ -197,6 +201,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
httpContext.Response.OnStarting(state =>
|
||||
{
|
||||
onStartingCalled = true;
|
||||
|
|
|
|||
|
|
@ -130,8 +130,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
var responseInfo = httpContext.Features.Get<IHttpResponseFeature>();
|
||||
var responseHeaders = responseInfo.Headers;
|
||||
responseHeaders["Connection"] = new string[] { "Close" };
|
||||
httpContext.Response.Body.Flush(); // Http.Sys adds the Content-Length: header for us if we don't flush
|
||||
return Task.FromResult(0);
|
||||
return httpContext.Response.Body.FlushAsync(); // Http.Sys adds the Content-Length: header for us if we don't flush
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(address);
|
||||
|
|
@ -204,6 +203,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Features.Get<IHttpBodyControlFeature>().AllowSynchronousIO = true;
|
||||
var responseInfo = httpContext.Features.Get<IHttpResponseFeature>();
|
||||
var responseHeaders = responseInfo.Headers;
|
||||
responseHeaders.Add("Custom1", new string[] { "value1a", "value1b" });
|
||||
|
|
|
|||
|
|
@ -53,12 +53,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
public async Task Server_EchoHelloWorld_Success()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
string input = new StreamReader(httpContext.Request.Body).ReadToEnd();
|
||||
var input = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
|
||||
Assert.Equal("Hello World", input);
|
||||
httpContext.Response.ContentLength = 11;
|
||||
return httpContext.Response.WriteAsync("Hello World");
|
||||
await httpContext.Response.WriteAsync("Hello World");
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(address, "Hello World");
|
||||
|
|
|
|||
Loading…
Reference in New Issue