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.Trailers.IsReadOnly = false;
Response.Headers.Clear(); Response.Headers.Clear();
Response.Trailers.Clear(); Response.Trailers.Clear();
SetFatalResponse(500);
if (ex is BadHttpRequestException badHttpRequestException)
{
SetFatalResponse(badHttpRequestException.StatusCode);
}
else
{
SetFatalResponse(StatusCodes.Status500InternalServerError);
}
} }
} }
finally finally

View File

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

View File

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

View File

@ -204,11 +204,33 @@ namespace Microsoft.AspNetCore.Server.HttpSys
})) }))
{ {
Task<string> requestTask = SendRequestAsync(address); 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 // Do it again to make sure the server didn't crash
requestTask = SendRequestAsync(address); 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);
} }
} }