Throw BadHttpRequestException in HttpSys (#24213)

This commit is contained in:
Kahbazi 2020-07-31 03:59:38 +04:30 committed by GitHub
parent d0cca519b4
commit 799014cfe7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 20 deletions

View File

@ -289,7 +289,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Response.Trailers.IsReadOnly = false;
Response.Headers.Clear();
Response.Trailers.Clear();
SetFatalResponse(500);
if (ex is BadHttpRequestException badHttpRequestException)
{
SetFatalResponse(badHttpRequestException.StatusCode);
}
else
{
SetFatalResponse(StatusCodes.Status500InternalServerError);
}
}
}
finally

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpSys.Internal;
using Microsoft.Extensions.Logging;
@ -432,8 +433,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
var contentLength = RequestContext.Request.ContentLength;
if (contentLength.HasValue && _maxSize.HasValue && contentLength.Value > _maxSize.Value)
{
throw new IOException(
$"The request's Content-Length {contentLength.Value} is larger than the request body size limit {_maxSize.Value}.");
throw new BadHttpRequestException(
$"The request's Content-Length {contentLength.Value} is larger than the request body size limit {_maxSize.Value}.",
StatusCodes.Status413PayloadTooLarge);
}
HasStarted = true;
@ -450,7 +452,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
_totalRead += bytesRead;
if (_maxSize.HasValue && _totalRead > _maxSize.Value)
{
exception = new IOException($"The total number of bytes read {_totalRead} has exceeded the request body size limit {_maxSize.Value}.");
exception = new BadHttpRequestException(
$"The total number of bytes read {_totalRead} has exceeded the request body size limit {_maxSize.Value}.",
StatusCodes.Status413PayloadTooLarge);
return true;
}
exception = null;

View File

@ -7,6 +7,7 @@ using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Testing;
using Xunit;
@ -159,10 +160,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.False(feature.IsReadOnly);
Assert.Equal(11, httpContext.Request.ContentLength);
byte[] input = new byte[100];
var ex = Assert.Throws<IOException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
var ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
ex = Assert.Throws<IOException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -182,10 +185,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.False(feature.IsReadOnly);
Assert.Equal(11, httpContext.Request.ContentLength);
byte[] input = new byte[100];
var ex = Assert.Throws<IOException>(() => { var t = httpContext.Request.Body.ReadAsync(input, 0, input.Length); });
var ex = Assert.Throws<BadHttpRequestException>(() => { var t = httpContext.Request.Body.ReadAsync(input, 0, input.Length); });
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
ex = Assert.Throws<IOException>(() => { var t = httpContext.Request.Body.ReadAsync(input, 0, input.Length); });
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = Assert.Throws<BadHttpRequestException>(() => { var t = httpContext.Request.Body.ReadAsync(input, 0, input.Length); });
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -205,10 +210,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.False(feature.IsReadOnly);
Assert.Equal(11, httpContext.Request.ContentLength);
byte[] input = new byte[100];
var ex = Assert.Throws<IOException>(() => httpContext.Request.Body.BeginRead(input, 0, input.Length, null, null));
var ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.BeginRead(input, 0, input.Length, null, null));
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
ex = Assert.Throws<IOException>(() => httpContext.Request.Body.BeginRead(input, 0, input.Length, null, null));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.BeginRead(input, 0, input.Length, null, null));
Assert.Equal("The request's Content-Length 11 is larger than the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -229,10 +236,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.False(feature.IsReadOnly);
Assert.Null(httpContext.Request.ContentLength);
byte[] input = new byte[100];
var ex = Assert.Throws<IOException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
var ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
ex = Assert.Throws<IOException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -252,9 +261,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.False(feature.IsReadOnly);
Assert.Null(httpContext.Request.ContentLength);
byte[] input = new byte[100];
var ex = await Assert.ThrowsAsync<IOException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
var ex = await Assert.ThrowsAsync<BadHttpRequestException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
ex = await Assert.ThrowsAsync<IOException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = await Assert.ThrowsAsync<BadHttpRequestException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
}, options => options.MaxRequestBodySize = 10))
{
@ -275,10 +286,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Assert.Null(httpContext.Request.ContentLength);
byte[] input = new byte[100];
var body = httpContext.Request.Body;
var ex = Assert.Throws<IOException>(() => body.EndRead(body.BeginRead(input, 0, input.Length, null, null)));
var ex = Assert.Throws<BadHttpRequestException>(() => body.EndRead(body.BeginRead(input, 0, input.Length, null, null)));
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
ex = Assert.Throws<IOException>(() => body.EndRead(body.BeginRead(input, 0, input.Length, null, null)));
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
ex = Assert.Throws<BadHttpRequestException>(() => body.EndRead(body.BeginRead(input, 0, input.Length, null, null)));
Assert.Equal("The total number of bytes read 11 has exceeded the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -303,8 +316,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
int read = httpContext.Request.Body.Read(input, 0, input.Length);
Assert.Equal(10, read);
content.Block.Release();
var ex = Assert.Throws<IOException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
var ex = Assert.Throws<BadHttpRequestException>(() => httpContext.Request.Body.Read(input, 0, input.Length));
Assert.Equal("The total number of bytes read 20 has exceeded the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
return Task.FromResult(0);
}, options => options.MaxRequestBodySize = 10))
{
@ -328,8 +342,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
int read = await httpContext.Request.Body.ReadAsync(input, 0, input.Length);
Assert.Equal(10, read);
content.Block.Release();
var ex = await Assert.ThrowsAsync<IOException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
var ex = await Assert.ThrowsAsync<BadHttpRequestException>(() => httpContext.Request.Body.ReadAsync(input, 0, input.Length));
Assert.Equal("The total number of bytes read 20 has exceeded the request body size limit 10.", ex.Message);
Assert.Equal(StatusCodes.Status413PayloadTooLarge, ex.StatusCode);
}, options => options.MaxRequestBodySize = 10))
{
string response = await SendRequestAsync(address, content, chunked: true);

View File

@ -204,11 +204,33 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}))
{
Task<string> requestTask = SendRequestAsync(address);
await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
var ex = await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
Assert.Equal(StatusCodes.Status500InternalServerError, (int)ex.StatusCode);
// Do it again to make sure the server didn't crash
requestTask = SendRequestAsync(address);
await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
ex = await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
Assert.Equal(StatusCodes.Status500InternalServerError, (int)ex.StatusCode);
}
}
[ConditionalFact]
public async Task Server_BadHttpRequestException_SetStatusCode()
{
string address;
using (Utilities.CreateHttpServer(out address, httpContext =>
{
throw new BadHttpRequestException("Something happened", StatusCodes.Status418ImATeapot);
}))
{
Task<string> requestTask = SendRequestAsync(address);
var ex = await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
Assert.Equal(StatusCodes.Status418ImATeapot, (int)ex.StatusCode);
// Do it again to make sure the server didn't crash
requestTask = SendRequestAsync(address);
ex = await Assert.ThrowsAsync<HttpRequestException>(async () => await requestTask);
Assert.Equal(StatusCodes.Status418ImATeapot, (int)ex.StatusCode);
}
}