Skip to content

Commit 6db3005

Browse files
committed
Disable AllowSynchronousIO by default in all servers #4774
1 parent 1f892d7 commit 6db3005

File tree

12 files changed

+221
-121
lines changed

12 files changed

+221
-121
lines changed

src/Hosting/TestHost/src/TestServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ public IWebHost Host
8181
/// Gets or sets a value that controls whether synchronous IO is allowed for the <see cref="HttpContext.Request"/> and <see cref="HttpContext.Response"/>
8282
/// </summary>
8383
/// <remarks>
84-
/// Defaults to true.
84+
/// Defaults to false.
8585
/// </remarks>
86-
public bool AllowSynchronousIO { get; set; } = true;
86+
public bool AllowSynchronousIO { get; set; } = false;
8787

8888
private IHttpApplication<Context> Application
8989
{

src/Servers/HttpSys/src/HttpSysOptions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -136,9 +136,9 @@ public long? MaxRequestBodySize
136136

137137
/// <summary>
138138
/// Gets or sets a value that controls whether synchronous IO is allowed for the HttpContext.Request.Body and HttpContext.Response.Body.
139-
/// The default is `true`.
139+
/// The default is `false`.
140140
/// </summary>
141-
public bool AllowSynchronousIO { get; set; } = true;
141+
public bool AllowSynchronousIO { get; set; } = false;
142142

143143
/// <summary>
144144
/// Gets or sets a value that controls how http.sys reacts when rejecting requests due to throttling conditions - like when the request

src/Servers/HttpSys/test/FunctionalTests/Listener/RequestBodyTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -17,26 +17,26 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
1717
public class RequestBodyTests
1818
{
1919
[ConditionalFact]
20-
public async Task RequestBody_SyncReadEnabledByDefault_ThrowsWhenDisabled()
20+
public async Task RequestBody_SyncReadDisabledByDefault_WorksWhenEnabled()
2121
{
2222
string address;
2323
using (var server = Utilities.CreateHttpServer(out address))
2424
{
2525
Task<string> responseTask = SendRequestAsync(address, "Hello World");
2626

27-
Assert.True(server.Options.AllowSynchronousIO);
27+
Assert.False(server.Options.AllowSynchronousIO);
2828

2929
var context = await server.AcceptAsync(Utilities.DefaultTimeout).Before(responseTask);
3030
byte[] input = new byte[100];
31+
Assert.Throws<InvalidOperationException>(() => context.Request.Body.Read(input, 0, input.Length));
32+
33+
context.AllowSynchronousIO = true;
3134

3235
Assert.True(context.AllowSynchronousIO);
3336
var read = context.Request.Body.Read(input, 0, input.Length);
3437
context.Response.ContentLength = read;
3538
context.Response.Body.Write(input, 0, read);
3639

37-
context.AllowSynchronousIO = false;
38-
Assert.Throws<InvalidOperationException>(() => context.Request.Body.Read(input, 0, input.Length));
39-
4040
string response = await responseTask;
4141
Assert.Equal("Hello World", response);
4242
}

src/Servers/HttpSys/test/FunctionalTests/Listener/ResponseBodyTests.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
1717
public class ResponseBodyTests
1818
{
1919
[ConditionalFact]
20-
public async Task ResponseBody_SyncWriteEnabledByDefault_ThrowsWhenDisabled()
20+
public async Task ResponseBody_SyncWriteDisabledByDefault_WorksWhenEnabled()
2121
{
2222
string address;
2323
using (var server = Utilities.CreateHttpServer(out address))
@@ -26,19 +26,17 @@ public async Task ResponseBody_SyncWriteEnabledByDefault_ThrowsWhenDisabled()
2626

2727
var context = await server.AcceptAsync(Utilities.DefaultTimeout).Before(responseTask);
2828

29-
Assert.True(context.AllowSynchronousIO);
30-
31-
context.Response.Body.Flush();
32-
context.Response.Body.Write(new byte[10], 0, 10);
33-
context.Response.Body.Flush();
34-
35-
context.AllowSynchronousIO = false;
29+
Assert.False(context.AllowSynchronousIO);
3630

3731
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Flush());
3832
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[10], 0, 10));
3933
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Flush());
4034

41-
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
35+
context.AllowSynchronousIO = true;
36+
37+
context.Response.Body.Flush();
38+
context.Response.Body.Write(new byte[10], 0, 10);
39+
context.Response.Body.Flush();
4240
context.Dispose();
4341

4442
var response = await responseTask;
@@ -47,7 +45,7 @@ public async Task ResponseBody_SyncWriteEnabledByDefault_ThrowsWhenDisabled()
4745
IEnumerable<string> ignored;
4846
Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length");
4947
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
50-
Assert.Equal(new byte[20], await response.Content.ReadAsByteArrayAsync());
48+
Assert.Equal(new byte[10], await response.Content.ReadAsByteArrayAsync());
5149
}
5250
}
5351

@@ -477,4 +475,4 @@ public async Task ResponseBody_ClientDisconnectsBeforeSecondWriteAsync_WriteComp
477475
}
478476
}
479477
}
480-
}
478+
}

src/Servers/IIS/IIS/src/Core/IISHttpContext.FeatureCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ unsafe X509Certificate2 ITlsConnectionFeature.ClientCertificate
320320

321321
IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator();
322322

323-
bool IHttpBodyControlFeature.AllowSynchronousIO { get; set; } = true;
323+
bool IHttpBodyControlFeature.AllowSynchronousIO { get; set; }
324324

325325
void IHttpBufferingFeature.DisableRequestBuffering()
326326
{

src/Servers/IIS/IIS/src/IISServerOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public class IISServerOptions
1111
/// Gets or sets a value that controls whether synchronous IO is allowed for the <see cref="HttpContext.Request"/> and <see cref="HttpContext.Response"/>
1212
/// </summary>
1313
/// <remarks>
14-
/// Defaults to true.
14+
/// Defaults to false.
1515
/// </remarks>
16-
public bool AllowSynchronousIO { get; set; } = true;
16+
public bool AllowSynchronousIO { get; set; } = false;
1717

1818
/// <summary>
1919
/// If true the server should set HttpContext.User. If false the server will only provide an
Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
54
using System.Threading.Tasks;
65
using Microsoft.AspNetCore.Http.Features;
76
using Microsoft.AspNetCore.Testing.xunit;
@@ -11,44 +10,22 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
1110
{
1211
[SkipIfHostableWebCoreNotAvailable]
1312
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")]
14-
public class HttpBodyControlFeatureTests : StrictTestServerTests
13+
public class ConnectionIdFeatureTests : StrictTestServerTests
1514
{
1615
[ConditionalFact]
17-
public async Task ThrowsOnSyncReadOrWrite()
16+
public async Task ProvidesConnectionId()
1817
{
19-
Exception writeException = null;
20-
Exception readException = null;
21-
using (var testServer = await TestServer.Create(
22-
ctx => {
23-
var bodyControl = ctx.Features.Get<IHttpBodyControlFeature>();
24-
bodyControl.AllowSynchronousIO = false;
25-
26-
try
27-
{
28-
ctx.Response.Body.Write(new byte[10]);
29-
}
30-
catch (Exception ex)
31-
{
32-
writeException = ex;
33-
}
34-
35-
try
36-
{
37-
ctx.Request.Body.Read(new byte[10]);
38-
}
39-
catch (Exception ex)
40-
{
41-
readException = ex;
42-
}
43-
44-
return Task.CompletedTask;
45-
}, LoggerFactory))
18+
string connectionId = null;
19+
using (var testServer = await TestServer.Create(ctx => {
20+
var connectionIdFeature = ctx.Features.Get<IHttpConnectionFeature>();
21+
connectionId = connectionIdFeature.ConnectionId;
22+
return Task.CompletedTask;
23+
}, LoggerFactory))
4624
{
4725
await testServer.HttpClient.GetStringAsync("/");
4826
}
4927

50-
Assert.IsType<InvalidOperationException>(readException);
51-
Assert.IsType<InvalidOperationException>(writeException);
28+
Assert.NotNull(connectionId);
5229
}
5330
}
5431
}
Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Http.Features;
67
using Microsoft.AspNetCore.Testing.xunit;
@@ -10,22 +11,44 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
1011
{
1112
[SkipIfHostableWebCoreNotAvailable]
1213
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, "https://github.com/aspnet/IISIntegration/issues/866")]
13-
public class ConnectionIdFeatureTests : StrictTestServerTests
14+
public class HttpBodyControlFeatureTests : StrictTestServerTests
1415
{
1516
[ConditionalFact]
16-
public async Task ProvidesConnectionId()
17+
public async Task ThrowsOnSyncReadOrWrite()
1718
{
18-
string connectionId = null;
19-
using (var testServer = await TestServer.Create(ctx => {
20-
var connectionIdFeature = ctx.Features.Get<IHttpConnectionFeature>();
21-
connectionId = connectionIdFeature.ConnectionId;
19+
Exception writeException = null;
20+
Exception readException = null;
21+
using (var testServer = await TestServer.Create(
22+
ctx => {
23+
var bodyControl = ctx.Features.Get<IHttpBodyControlFeature>();
24+
Assert.False(bodyControl.AllowSynchronousIO);
25+
26+
try
27+
{
28+
ctx.Response.Body.Write(new byte[10]);
29+
}
30+
catch (Exception ex)
31+
{
32+
writeException = ex;
33+
}
34+
35+
try
36+
{
37+
ctx.Request.Body.Read(new byte[10]);
38+
}
39+
catch (Exception ex)
40+
{
41+
readException = ex;
42+
}
43+
2244
return Task.CompletedTask;
2345
}, LoggerFactory))
2446
{
2547
await testServer.HttpClient.GetStringAsync("/");
2648
}
2749

28-
Assert.NotNull(connectionId);
50+
Assert.IsType<InvalidOperationException>(readException);
51+
Assert.IsType<InvalidOperationException>(writeException);
2952
}
3053
}
3154
}

src/Servers/Kestrel/Core/src/KestrelServerOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ public class KestrelServerOptions
5050
/// Gets or sets a value that controls whether synchronous IO is allowed for the <see cref="HttpContext.Request"/> and <see cref="HttpContext.Response"/>
5151
/// </summary>
5252
/// <remarks>
53-
/// Defaults to true.
53+
/// Defaults to false.
5454
/// </remarks>
55-
public bool AllowSynchronousIO { get; set; } = true;
55+
public bool AllowSynchronousIO { get; set; } = false;
5656

5757
/// <summary>
5858
/// Enables the Listen options callback to resolve and use services registered by the application during startup.

src/Servers/Kestrel/Core/test/KestrelServerOptionsTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ public void NoDelayDefaultsToTrue()
2323
}
2424

2525
[Fact]
26-
public void AllowSynchronousIODefaultsToTrue()
26+
public void AllowSynchronousIODefaultsToFalse()
2727
{
2828
var options = new KestrelServerOptions();
2929

30-
Assert.True(options.AllowSynchronousIO);
30+
Assert.False(options.AllowSynchronousIO);
3131
}
3232

3333
[Fact]
@@ -65,4 +65,4 @@ public void ConfigureEndpointDefaultsAppliesToNewEndpoints()
6565
Assert.False(options.ListenOptions[3].NoDelay);
6666
}
6767
}
68-
}
68+
}

0 commit comments

Comments
 (0)