diff --git a/src/Servers/IIS/IIS/src/Core/IISConfigurationData.cs b/src/Servers/IIS/IIS/src/Core/IISConfigurationData.cs index 21d00ed097..8fdf384467 100644 --- a/src/Servers/IIS/IIS/src/Core/IISConfigurationData.cs +++ b/src/Servers/IIS/IIS/src/Core/IISConfigurationData.cs @@ -19,6 +19,6 @@ namespace Microsoft.AspNetCore.Server.IIS.Core public bool fAnonymousAuthEnable; [MarshalAs(UnmanagedType.BStr)] public string pwzBindings; - public int maxRequestBodySize; + public uint maxRequestBodySize; } } diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs index dad75729e3..c8f9f4505c 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs @@ -3,8 +3,6 @@ using System; using System.Buffers; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting.Server; diff --git a/src/Servers/IIS/IIS/src/IISServerOptions.cs b/src/Servers/IIS/IIS/src/IISServerOptions.cs index bf83ca2e2e..430f1b3b77 100644 --- a/src/Servers/IIS/IIS/src/IISServerOptions.cs +++ b/src/Servers/IIS/IIS/src/IISServerOptions.cs @@ -42,16 +42,17 @@ namespace Microsoft.AspNetCore.Builder // https://www.iis.net/configreference/system.webserver/security/requestfiltering/requestlimits#005 private long? _maxRequestBodySize = 30000000; - internal long IisMaxRequestSizeLimit; + internal long IisMaxRequestSizeLimit; // Used for verifying if limit set in managed exceeds native /// /// Gets or sets the maximum allowed size of any request body in bytes. - /// When set to null, the maximum request body size is unlimited. + /// When set to null, the maximum request length will not be restricted in ASP.NET Core. + /// However, the IIS maxAllowedContentLength will still restrict content length requests (30,000,000 by default). /// This limit has no effect on upgraded connections which are always unlimited. /// This can be overridden per-request via . /// /// - /// Defaults to null (unlimited). + /// Defaults to 30,000,000 bytes (~28.6 MB). /// public long? MaxRequestBodySize { diff --git a/src/Servers/IIS/IIS/src/WebHostBuilderIISExtensions.cs b/src/Servers/IIS/IIS/src/WebHostBuilderIISExtensions.cs index fa52725c0a..0a4dd7e4d7 100644 --- a/src/Servers/IIS/IIS/src/WebHostBuilderIISExtensions.cs +++ b/src/Servers/IIS/IIS/src/WebHostBuilderIISExtensions.cs @@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.Hosting options => { options.ServerAddresses = iisConfigData.pwzBindings.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); options.ForwardWindowsAuthentication = iisConfigData.fWindowsAuthEnabled || iisConfigData.fBasicAuthEnabled; + options.MaxRequestBodySize = iisConfigData.maxRequestBodySize; options.IisMaxRequestSizeLimit = iisConfigData.maxRequestBodySize; } ); diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/MaxRequestBodySizeTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/MaxRequestBodySizeTests.cs index f8e88efa84..e4d951c63f 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/MaxRequestBodySizeTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/MaxRequestBodySizeTests.cs @@ -54,6 +54,46 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess Assert.True(result.StatusCode == HttpStatusCode.NotFound || result.StatusCode == HttpStatusCode.RequestEntityTooLarge); } + [ConditionalFact] + [RequiresNewHandler] + public async Task SetIISLimitMaxRequestBodySizeE2EWorksWithLargerLimit() + { + var deploymentParameters = Fixture.GetBaseDeploymentParameters(); + deploymentParameters.ServerConfigActionList.Add( + (config, _) => { + config + .RequiredElement("system.webServer") + .GetOrAdd("security") + .GetOrAdd("requestFiltering") + .GetOrAdd("requestLimits", "maxAllowedContentLength", "100000000"); + }); + var deploymentResult = await DeployAsync(deploymentParameters); + + var result = await deploymentResult.HttpClient.PostAsync("/ReadRequestBodyLarger", new StringContent(new string('a', 100000000))); + + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + } + + [ConditionalFact] + [RequiresNewHandler] + public async Task SetIISLimitMaxRequestBodySizeE2EWorksWithIntMaxValue() + { + var deploymentParameters = Fixture.GetBaseDeploymentParameters(); + deploymentParameters.ServerConfigActionList.Add( + (config, _) => { + config + .RequiredElement("system.webServer") + .GetOrAdd("security") + .GetOrAdd("requestFiltering") + .GetOrAdd("requestLimits", "maxAllowedContentLength", "4294967295"); + }); + var deploymentResult = await DeployAsync(deploymentParameters); + + var result = await deploymentResult.HttpClient.PostAsync("/ReadRequestBodyLarger", new StringContent(new string('a', 10000))); + + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + } + [ConditionalFact] [RequiresNewHandler] public async Task IISRejectsContentLengthTooLargeByDefault() @@ -94,7 +134,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess }); var deploymentResult = await DeployAsync(deploymentParameters); - var result = await deploymentResult.HttpClient.PostAsync("/DecreaseRequestLimit", new StringContent("1")); + var result = await deploymentResult.HttpClient.PostAsync("/IncreaseRequestLimit", new StringContent("1")); Assert.Equal(HttpStatusCode.OK, result.StatusCode); StopServer(); diff --git a/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs b/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs index ef7223b2d5..0d23030f82 100644 --- a/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs +++ b/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs @@ -478,6 +478,16 @@ namespace TestSite } } + private async Task ReadRequestBodyLarger(HttpContext ctx) + { + var readBuffer = new byte[4096]; + var result = await ctx.Request.Body.ReadAsync(readBuffer, 0, 4096); + while (result != 0) + { + result = await ctx.Request.Body.ReadAsync(readBuffer, 0, 4096); + } + } + private int _requestsInFlight = 0; private async Task ReadAndCountRequestBody(HttpContext ctx) { @@ -1444,6 +1454,13 @@ namespace TestSite await Assert.ThrowsAsync(() => readTask); } + public Task IncreaseRequestLimit(HttpContext httpContext) + { + var maxRequestBodySizeFeature = httpContext.Features.Get(); + maxRequestBodySizeFeature.MaxRequestBodySize = 2; + return Task.CompletedTask; + } + internal static readonly HashSet<(string, StringValues, StringValues)> NullTrailers = new HashSet<(string, StringValues, StringValues)>() { ("NullString", (string)null, (string)null),