mirror of https://github.com/abpframework/abp.git
committed by
GitHub
8 changed files with 0 additions and 301 deletions
@ -1,81 +0,0 @@ |
|||||
using System.Globalization; |
|
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.AspNetCore.Http.Features; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.RequestSizeLimit; |
|
||||
|
|
||||
public class AbpRequestSizeLimitMiddleware : IMiddleware, ITransientDependency |
|
||||
{ |
|
||||
private readonly ILogger<AbpRequestSizeLimitMiddleware> _logger; |
|
||||
|
|
||||
public AbpRequestSizeLimitMiddleware(ILogger<AbpRequestSizeLimitMiddleware> logger) |
|
||||
{ |
|
||||
_logger = logger; |
|
||||
} |
|
||||
|
|
||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
|
||||
{ |
|
||||
var endpoint = context.GetEndpoint(); |
|
||||
if (endpoint != null) |
|
||||
{ |
|
||||
if (!HasDisableRequestSizeLimitAttribute(endpoint)) |
|
||||
{ |
|
||||
var attribute = endpoint.Metadata.GetMetadata<AbpRequestSizeLimitAttribute>(); |
|
||||
if (attribute != null) |
|
||||
{ |
|
||||
var maxRequestBodySizeFeature = context.Features.Get<IHttpMaxRequestBodySizeFeature>(); |
|
||||
if (maxRequestBodySizeFeature == null) |
|
||||
{ |
|
||||
_logger.LogInformation("A request body size limit could not be applied. This server does not support the IHttpRequestBodySizeFeature."); |
|
||||
} |
|
||||
else if (maxRequestBodySizeFeature.IsReadOnly) |
|
||||
{ |
|
||||
_logger.LogInformation("A request body size limit could not be applied. The IHttpRequestBodySizeFeature for the server is read-only."); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
_logger.LogInformation($"The maximum request body size has been set to {attribute.GetBytes().ToString(CultureInfo.InvariantCulture)}."); |
|
||||
maxRequestBodySizeFeature.MaxRequestBodySize = attribute.GetBytes(); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
_logger.LogInformation($"AbpRequestSizeLimitAttribute does not exist in endpoint, Skipping."); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
_logger.LogInformation($"Endpoint has DisableRequestSizeLimitAttribute, Skipping."); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
_logger.LogInformation($"Endpoint is null, Skipping."); |
|
||||
} |
|
||||
|
|
||||
await next(context); |
|
||||
} |
|
||||
|
|
||||
protected virtual bool HasDisableRequestSizeLimitAttribute(Endpoint endpoint) |
|
||||
{ |
|
||||
foreach (var metadata in endpoint.Metadata.Reverse()) |
|
||||
{ |
|
||||
if (metadata is AbpRequestSizeLimitAttribute) |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
if (metadata is DisableRequestSizeLimitAttribute) |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.RequestSizeLimit; |
|
||||
|
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] |
|
||||
public class AbpRequestSizeLimitAttribute : Attribute |
|
||||
{ |
|
||||
private readonly long _bytes; |
|
||||
|
|
||||
public AbpRequestSizeLimitAttribute(long bytes) |
|
||||
{ |
|
||||
_bytes = bytes; |
|
||||
} |
|
||||
|
|
||||
public long GetBytes() |
|
||||
{ |
|
||||
return _bytes; |
|
||||
} |
|
||||
} |
|
||||
@ -1,94 +0,0 @@ |
|||||
using System; |
|
||||
using System.IO; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Http.Features; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.RequestSizeLimit; |
|
||||
|
|
||||
public class RequestBodySizeCheckingStream : Stream |
|
||||
{ |
|
||||
private readonly Stream _innerStream; |
|
||||
private readonly IHttpMaxRequestBodySizeFeature _maxRequestBodySizeFeature; |
|
||||
private long _totalRead; |
|
||||
|
|
||||
public RequestBodySizeCheckingStream(Stream innerStream, IHttpMaxRequestBodySizeFeature maxRequestBodySizeFeature) |
|
||||
{ |
|
||||
_innerStream = innerStream; |
|
||||
_maxRequestBodySizeFeature = maxRequestBodySizeFeature; |
|
||||
} |
|
||||
|
|
||||
public override bool CanRead => _innerStream.CanRead; |
|
||||
|
|
||||
public override bool CanSeek => _innerStream.CanSeek; |
|
||||
|
|
||||
public override bool CanWrite => _innerStream.CanWrite; |
|
||||
|
|
||||
public override long Length => _innerStream.Length; |
|
||||
|
|
||||
public override long Position |
|
||||
{ |
|
||||
get { return _innerStream.Position; } |
|
||||
set { _innerStream.Position = value; } |
|
||||
} |
|
||||
|
|
||||
public override void Flush() |
|
||||
{ |
|
||||
_innerStream.Flush(); |
|
||||
} |
|
||||
|
|
||||
public override int Read(byte[] buffer, int offset, int count) |
|
||||
{ |
|
||||
if (_maxRequestBodySizeFeature.MaxRequestBodySize != null && _innerStream.CanSeek && _innerStream.Length > _maxRequestBodySizeFeature.MaxRequestBodySize) |
|
||||
{ |
|
||||
throw new BusinessException("Request content size is greater than the limit size"); |
|
||||
} |
|
||||
|
|
||||
var read = _innerStream.Read(buffer, offset, count); |
|
||||
_totalRead += read; |
|
||||
|
|
||||
if (_maxRequestBodySizeFeature.MaxRequestBodySize != null && _totalRead > _maxRequestBodySizeFeature.MaxRequestBodySize) |
|
||||
{ |
|
||||
throw new BusinessException("Request content size is greater than the limit size"); |
|
||||
} |
|
||||
return read; |
|
||||
} |
|
||||
|
|
||||
public async override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) |
|
||||
{ |
|
||||
if (_maxRequestBodySizeFeature.MaxRequestBodySize != null && _innerStream.CanSeek && _innerStream.Length > _maxRequestBodySizeFeature.MaxRequestBodySize) |
|
||||
{ |
|
||||
throw new BusinessException("Request content size is greater than the limit size"); |
|
||||
} |
|
||||
|
|
||||
var read = await _innerStream.ReadAsync(buffer, offset, count, cancellationToken); |
|
||||
_totalRead += read; |
|
||||
|
|
||||
if (_maxRequestBodySizeFeature.MaxRequestBodySize != null && _totalRead > _maxRequestBodySizeFeature.MaxRequestBodySize) |
|
||||
{ |
|
||||
throw new BusinessException("Request content size is greater than the limit size"); |
|
||||
} |
|
||||
return read; |
|
||||
} |
|
||||
|
|
||||
public override long Seek(long offset, SeekOrigin origin) |
|
||||
{ |
|
||||
return _innerStream.Seek(offset, origin); |
|
||||
} |
|
||||
|
|
||||
public override void SetLength(long value) |
|
||||
{ |
|
||||
_innerStream.SetLength(value); |
|
||||
} |
|
||||
|
|
||||
public override void Write(byte[] buffer, int offset, int count) |
|
||||
{ |
|
||||
_innerStream.Write(buffer, offset, count); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public class TestHttpMaxRequestBodySizeFeature : IHttpMaxRequestBodySizeFeature |
|
||||
{ |
|
||||
public bool IsReadOnly => false; |
|
||||
public long? MaxRequestBodySize { get; set; } |
|
||||
} |
|
||||
@ -1,25 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Volo.Abp.AspNetCore.RequestSizeLimit; |
|
||||
using Volo.Abp.Content; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.RequestSizeLimit; |
|
||||
|
|
||||
[Route("api/request-siz-limit")] |
|
||||
[AbpRequestSizeLimit(5)] |
|
||||
public class RequestSizeLimitController : AbpController |
|
||||
{ |
|
||||
[HttpPost] |
|
||||
[Route("check")] |
|
||||
public string RequestSizeLimitCheck(IRemoteStreamContent file) |
|
||||
{ |
|
||||
return !ModelState.IsValid ? ModelState.ToString() : "ok"; |
|
||||
} |
|
||||
|
|
||||
[HttpPost] |
|
||||
[DisableRequestSizeLimit] |
|
||||
[Route("disable")] |
|
||||
public string DisableRequestSizeLimit(IRemoteStreamContent file) |
|
||||
{ |
|
||||
return !ModelState.IsValid ? ModelState.ToString() : "ok"; |
|
||||
} |
|
||||
} |
|
||||
@ -1,53 +0,0 @@ |
|||||
using System.Globalization; |
|
||||
using System.IO; |
|
||||
using System.Net; |
|
||||
using System.Net.Http; |
|
||||
using System.Net.Http.Headers; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
using Shouldly; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.RequestSizeLimit; |
|
||||
|
|
||||
public class RequestSizeLimitController_Tests : AspNetCoreMvcTestBase |
|
||||
{ |
|
||||
[Fact] |
|
||||
public async Task RequestSizeLimitCheck_Test() |
|
||||
{ |
|
||||
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, "api/request-siz-limit/check")) |
|
||||
{ |
|
||||
var memoryStream = new MemoryStream(); |
|
||||
await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("0123456789")); |
|
||||
memoryStream.Position = 0; |
|
||||
|
|
||||
var streamContent = new StreamContent(memoryStream); |
|
||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); |
|
||||
requestMessage.Content = new MultipartFormDataContent { { streamContent, "file", "text.txt" } }; |
|
||||
|
|
||||
var response = await Client.SendAsync(requestMessage); |
|
||||
|
|
||||
(await response.Content.ReadAsStringAsync()).ShouldContain("Request content size is greater than the limit size"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task DisableRequestSizeLimit_Test() |
|
||||
{ |
|
||||
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, "api/request-siz-limit/disable")) |
|
||||
{ |
|
||||
var memoryStream = new MemoryStream(); |
|
||||
await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("0123456789")); |
|
||||
memoryStream.Position = 0; |
|
||||
|
|
||||
var streamContent = new StreamContent(memoryStream); |
|
||||
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); |
|
||||
requestMessage.Content = new MultipartFormDataContent { { streamContent, "file", "text.txt" } }; |
|
||||
|
|
||||
var response = await Client.SendAsync(requestMessage); |
|
||||
|
|
||||
(await response.Content.ReadAsStringAsync()).ShouldContain("ok"); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue