parent
579aca0121
commit
17f6b17a6d
|
|
@ -176,6 +176,12 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<IFilterProvider, DefaultFilterProvider>());
|
||||
|
||||
//
|
||||
// Resource Filters
|
||||
//
|
||||
services.TryAddTransient<RequestSizeLimitResourceFilter>();
|
||||
services.TryAddTransient<DisableRequestSizeLimitResourceFilter>();
|
||||
|
||||
//
|
||||
// ModelBinding, Validation
|
||||
//
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Disables the request body size limit.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class DisableRequestSizeLimitAttribute : Attribute, IFilterFactory, IOrderedFilter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
var filter = serviceProvider.GetRequiredService<DisableRequestSizeLimitResourceFilter>();
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// A marker interface for filters which define a policy for maximum size for the request body.
|
||||
/// </summary>
|
||||
public interface IRequestSizePolicy : IFilterMetadata
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A filter that sets <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to <c>null</c>.
|
||||
/// </summary>
|
||||
public class DisableRequestSizeLimitResourceFilter : IResourceFilter, IRequestSizePolicy
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DisableRequestSizeLimitResourceFilter"/>.
|
||||
/// </summary>
|
||||
public DisableRequestSizeLimitResourceFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<DisableRequestSizeLimitResourceFilter>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to <c>null</c>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
/// <remarks>If <see cref="IHttpMaxRequestBodySizeFeature"/> is not enabled or is read-only,
|
||||
/// the <see cref="DisableRequestSizeLimitAttribute"/> is not applied.</remarks>
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (IsClosestRequestSizePolicy(context.Filters))
|
||||
{
|
||||
var maxRequestBodySizeFeature = context.HttpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
|
||||
if (maxRequestBodySizeFeature == null)
|
||||
{
|
||||
_logger.FeatureNotFound();
|
||||
}
|
||||
else if (maxRequestBodySizeFeature.IsReadOnly)
|
||||
{
|
||||
_logger.FeatureIsReadOnly();
|
||||
}
|
||||
else
|
||||
{
|
||||
maxRequestBodySizeFeature.MaxRequestBodySize = null;
|
||||
_logger.RequestBodySizeLimitDisabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsClosestRequestSizePolicy(IList<IFilterMetadata> filters)
|
||||
{
|
||||
// Determine if this instance is the 'effective' request size policy.
|
||||
for (var i = filters.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var filter = filters[i];
|
||||
if (filter is IRequestSizePolicy)
|
||||
{
|
||||
return ReferenceEquals(this, filter);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Fail("The current instance should be in the list of filters.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,11 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
private static readonly Action<ILogger, string, Exception> _redirectToPageResultExecuting;
|
||||
|
||||
private static readonly Action<ILogger, Exception> _featureNotFound;
|
||||
private static readonly Action<ILogger, Exception> _featureIsReadOnly;
|
||||
private static readonly Action<ILogger, string, Exception> _maxRequestBodySizeSet;
|
||||
private static readonly Action<ILogger, Exception> _requestBodySizeLimitDisabled;
|
||||
|
||||
static MvcCoreLoggerExtensions()
|
||||
{
|
||||
_actionExecuting = LoggerMessage.Define<string>(
|
||||
|
|
@ -243,6 +248,26 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
LogLevel.Debug,
|
||||
3,
|
||||
"No actions matched the current request. Route values: {RouteValues}");
|
||||
|
||||
_featureNotFound = LoggerMessage.Define(
|
||||
LogLevel.Warning,
|
||||
1,
|
||||
"A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature.");
|
||||
|
||||
_featureIsReadOnly = LoggerMessage.Define(
|
||||
LogLevel.Warning,
|
||||
2,
|
||||
"A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only.");
|
||||
|
||||
_maxRequestBodySizeSet = LoggerMessage.Define<string>(
|
||||
LogLevel.Debug,
|
||||
3,
|
||||
"The maximum request body size has been set to {RequestSize}.");
|
||||
|
||||
_requestBodySizeLimitDisabled = LoggerMessage.Define(
|
||||
LogLevel.Debug,
|
||||
3,
|
||||
"The request body size limit has been disabled.");
|
||||
}
|
||||
|
||||
public static IDisposable ActionScope(this ILogger logger, ActionDescriptor action)
|
||||
|
|
@ -522,6 +547,26 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public static void RedirectToPageResultExecuting(this ILogger logger, string page)
|
||||
=> _redirectToPageResultExecuting(logger, page, null);
|
||||
|
||||
public static void FeatureNotFound(this ILogger logger)
|
||||
{
|
||||
_featureNotFound(logger, null);
|
||||
}
|
||||
|
||||
public static void FeatureIsReadOnly(this ILogger logger)
|
||||
{
|
||||
_featureIsReadOnly(logger, null);
|
||||
}
|
||||
|
||||
public static void MaxRequestBodySizeSet(this ILogger logger, string requestSize)
|
||||
{
|
||||
_maxRequestBodySizeSet(logger, requestSize, null);
|
||||
}
|
||||
|
||||
public static void RequestBodySizeLimitDisabled(this ILogger logger)
|
||||
{
|
||||
_requestBodySizeLimitDisabled(logger, null);
|
||||
}
|
||||
|
||||
private class ActionLogScope : IReadOnlyList<KeyValuePair<string, object>>
|
||||
{
|
||||
private readonly ActionDescriptor _action;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A filter that sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/>
|
||||
/// to the specified <see cref="Bytes"/>.
|
||||
/// </summary>
|
||||
public class RequestSizeLimitResourceFilter : IResourceFilter, IRequestSizePolicy
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RequestSizeLimitResourceFilter"/>.
|
||||
/// </summary>
|
||||
public RequestSizeLimitResourceFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<RequestSizeLimitResourceFilter>();
|
||||
}
|
||||
|
||||
public long Bytes { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnResourceExecuted(ResourceExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="IHttpMaxRequestBodySizeFeature.MaxRequestBodySize"/> to <see cref="Bytes"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ResourceExecutingContext"/>.</param>
|
||||
/// <remarks>If <see cref="IHttpMaxRequestBodySizeFeature"/> is not enabled or is read-only,
|
||||
/// the <see cref="RequestSizeLimitAttribute"/> is not applied.</remarks>
|
||||
public void OnResourceExecuting(ResourceExecutingContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (IsClosestRequestSizePolicy(context.Filters))
|
||||
{
|
||||
var maxRequestBodySizeFeature = context.HttpContext.Features.Get<IHttpMaxRequestBodySizeFeature>();
|
||||
|
||||
if (maxRequestBodySizeFeature == null)
|
||||
{
|
||||
_logger.FeatureNotFound();
|
||||
}
|
||||
else if (maxRequestBodySizeFeature.IsReadOnly)
|
||||
{
|
||||
_logger.FeatureIsReadOnly();
|
||||
}
|
||||
else
|
||||
{
|
||||
maxRequestBodySizeFeature.MaxRequestBodySize = Bytes;
|
||||
_logger.MaxRequestBodySizeSet(Bytes.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsClosestRequestSizePolicy(IList<IFilterMetadata> filters)
|
||||
{
|
||||
// Determine if this instance is the 'effective' request size policy.
|
||||
for (var i = filters.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var filter = filters[i];
|
||||
if (filter is IRequestSizePolicy)
|
||||
{
|
||||
return ReferenceEquals(this, filter);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Fail("The current instance should be in the list of filters.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the request body size limit to the specified size.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class RequestSizeLimitAttribute : Attribute, IFilterFactory, IOrderedFilter
|
||||
{
|
||||
private readonly long _bytes;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RequestSizeLimitAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The request body size limit.</param>
|
||||
public RequestSizeLimitAttribute(long bytes)
|
||||
{
|
||||
_bytes = bytes;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Order { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsReusable => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
|
||||
{
|
||||
var filter = serviceProvider.GetRequiredService<RequestSizeLimitResourceFilter>();
|
||||
filter.Bytes = _bytes;
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class DisableRequestSizeLimitResourceFilterTest
|
||||
{
|
||||
[Fact]
|
||||
public void SetsMaxRequestBodySizeToNull()
|
||||
{
|
||||
// Arrange
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkipsWhenOverridden()
|
||||
{
|
||||
// Arrange
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var disableRequestSizeLimitResourceFilterFinal = new DisableRequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter, disableRequestSizeLimitResourceFilterFinal });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
disableRequestSizeLimitResourceFilterFinal.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
Assert.Equal(1, httpMaxRequestBodySize.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsFeatureNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature.",
|
||||
write.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsFeatureIsReadOnly()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
httpMaxRequestBodySize.IsReadOnly = true;
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only.", write.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsMaxRequestBodySizeSetToNull()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var disableRequestSizeLimitResourceFilter = new DisableRequestSizeLimitResourceFilter(loggerFactory);
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { disableRequestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
disableRequestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"The request body size limit has been disabled.", write.State.ToString());
|
||||
}
|
||||
|
||||
private static ResourceExecutingContext CreateResourceExecutingContext(IFilterMetadata[] filters)
|
||||
{
|
||||
return new ResourceExecutingContext(
|
||||
CreateActionContext(),
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
{
|
||||
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||
}
|
||||
|
||||
private class TestHttpMaxRequestBodySizeFeature : IHttpMaxRequestBodySizeFeature
|
||||
{
|
||||
private long? _maxRequestBodySize;
|
||||
|
||||
public bool IsReadOnly { get; set; }
|
||||
|
||||
public long? MaxRequestBodySize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxRequestBodySize;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxRequestBodySize = value;
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class RequestSizeLimitResourceFilterTest
|
||||
{
|
||||
[Fact]
|
||||
public void SetsMaxRequestBodySize()
|
||||
{
|
||||
// Arrange
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12345, httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SkipsWhenOverridden()
|
||||
{
|
||||
// Arrange
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var requestSizeLimitResourceFilterFinal = new RequestSizeLimitResourceFilter(NullLoggerFactory.Instance);
|
||||
requestSizeLimitResourceFilterFinal.Bytes = 0;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter, requestSizeLimitResourceFilterFinal });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
requestSizeLimitResourceFilterFinal.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, httpMaxRequestBodySize.MaxRequestBodySize);
|
||||
Assert.Equal(1, httpMaxRequestBodySize.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsFeatureNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature.",
|
||||
write.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsFeatureIsReadOnly()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
httpMaxRequestBodySize.IsReadOnly = true;
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only.", write.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogsMaxRequestBodySizeSet()
|
||||
{
|
||||
// Arrange
|
||||
var sink = new TestSink();
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
|
||||
var requestSizeLimitResourceFilter = new RequestSizeLimitResourceFilter(loggerFactory);
|
||||
requestSizeLimitResourceFilter.Bytes = 12345;
|
||||
var resourceExecutingContext = CreateResourceExecutingContext(new IFilterMetadata[] { requestSizeLimitResourceFilter });
|
||||
|
||||
var httpMaxRequestBodySize = new TestHttpMaxRequestBodySizeFeature();
|
||||
resourceExecutingContext.HttpContext.Features.Set<IHttpMaxRequestBodySizeFeature>(httpMaxRequestBodySize);
|
||||
|
||||
// Act
|
||||
requestSizeLimitResourceFilter.OnResourceExecuting(resourceExecutingContext);
|
||||
|
||||
// Assert
|
||||
var write = Assert.Single(sink.Writes);
|
||||
Assert.Equal($"The maximum request body size has been set to 12345.", write.State.ToString());
|
||||
}
|
||||
|
||||
private static ResourceExecutingContext CreateResourceExecutingContext(IFilterMetadata[] filters)
|
||||
{
|
||||
return new ResourceExecutingContext(
|
||||
CreateActionContext(),
|
||||
filters,
|
||||
new List<IValueProviderFactory>());
|
||||
}
|
||||
|
||||
private static ActionContext CreateActionContext()
|
||||
{
|
||||
return new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
|
||||
}
|
||||
|
||||
private class TestHttpMaxRequestBodySizeFeature : IHttpMaxRequestBodySizeFeature
|
||||
{
|
||||
private long? _maxRequestBodySize;
|
||||
|
||||
public bool IsReadOnly { get; set; }
|
||||
|
||||
public long? MaxRequestBodySize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxRequestBodySize;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxRequestBodySize = value;
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace FiltersWebSite
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue