mirror of https://github.com/abpframework/abp.git
6 changed files with 213 additions and 2 deletions
@ -0,0 +1,94 @@ |
|||
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; } |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
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"; |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
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