From b463e049b6aed02f94edcac8855b8b5c87d0989b Mon Sep 17 00:00:00 2001 From: Chris Oliver Date: Mon, 6 Apr 2020 22:42:16 +0100 Subject: [PATCH] Move BadHttpRequestException to Http.Abstractions (#20339) --- ...AspNetCore.Http.Abstractions.netcoreapp.cs | 8 + .../src/BadHttpRequestException.cs | 60 +++++++ ...rosoft.AspNetCore.Server.IIS.netcoreapp.cs | 7 +- .../IIS/IIS/src/BadHttpRequestException.cs | 32 +--- .../IIS/IIS/src/Core/IISHttpContext.IO.cs | 2 +- .../IIS/IIS/src/Core/IISHttpContext.Log.cs | 2 +- .../IIS/IIS/src/Core/IISHttpContext.cs | 4 +- .../IIS/IIS/src/Core/IISHttpContextOfT.cs | 2 + .../IIS/IIS/src/IISBadHttpRequestException.cs | 36 ++++ .../test/IIS.Tests/MaxRequestBodySizeTests.cs | 10 +- ...pNetCore.Server.Kestrel.Core.netcoreapp.cs | 7 +- .../Core/src/BadHttpRequestException.cs | 158 +---------------- .../Http/Http1ChunkedEncodingMessageBody.cs | 9 +- .../Core/src/Internal/Http/Http1Connection.cs | 29 ++-- .../Http/Http1ContentLengthMessageBody.cs | 6 +- .../src/Internal/Http/Http1MessageBody.cs | 12 +- .../Core/src/Internal/Http/HttpParser.cs | 7 +- .../Core/src/Internal/Http/HttpProtocol.cs | 14 +- .../src/Internal/Http/HttpRequestHeaders.cs | 6 +- .../Core/src/Internal/Http/MessageBody.cs | 2 +- .../src/Internal/Http2/Http2Connection.cs | 4 +- .../src/Internal/Http2/Http2MessageBody.cs | 2 +- .../src/Internal/Http3/Http3ControlStream.cs | 2 +- .../src/Internal/Http3/Http3MessageBody.cs | 2 +- .../Core/src/Internal/Http3/Http3Stream.cs | 4 +- .../Internal/Infrastructure/HttpUtilities.cs | 2 +- .../Internal/Infrastructure/IKestrelTrace.cs | 2 +- .../Internal/Infrastructure/KestrelTrace.cs | 2 +- .../src/KestralBadHttpRequestException.cs | 159 ++++++++++++++++++ .../Kestrel/Core/test/Http1ConnectionTests.cs | 24 +++ .../Kestrel/Core/test/HttpParserTests.cs | 26 ++- .../Core/test/HttpRequestHeadersTests.cs | 2 + .../Kestrel/Core/test/MessageBodyTests.cs | 24 +++ .../Kestrel.Performance/Mocks/MockTrace.cs | 3 +- .../Kestrel/samples/SampleApp/Startup.cs | 2 +- .../shared/test/CompositeKestrelTrace.cs | 2 +- .../BadHttpRequestTests.cs | 2 + .../ChunkedRequestTests.cs | 5 + .../Http2/Http2StreamTests.cs | 12 ++ .../Http2/Http2TimeoutTests.cs | 2 +- .../MaxRequestBodySizeTests.cs | 25 +++ .../RequestBodyTimeoutTests.cs | 2 +- .../InMemory.FunctionalTests/ResponseTests.cs | 19 ++- 43 files changed, 494 insertions(+), 248 deletions(-) create mode 100644 src/Http/Http.Abstractions/src/BadHttpRequestException.cs create mode 100644 src/Servers/IIS/IIS/src/IISBadHttpRequestException.cs create mode 100644 src/Servers/Kestrel/Core/src/KestralBadHttpRequestException.cs diff --git a/src/Http/Http.Abstractions/ref/Microsoft.AspNetCore.Http.Abstractions.netcoreapp.cs b/src/Http/Http.Abstractions/ref/Microsoft.AspNetCore.Http.Abstractions.netcoreapp.cs index 850f4c3569..1ece9f3acd 100644 --- a/src/Http/Http.Abstractions/ref/Microsoft.AspNetCore.Http.Abstractions.netcoreapp.cs +++ b/src/Http/Http.Abstractions/ref/Microsoft.AspNetCore.Http.Abstractions.netcoreapp.cs @@ -97,6 +97,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure } namespace Microsoft.AspNetCore.Http { + public partial class BadHttpRequestException : System.IO.IOException + { + public BadHttpRequestException(string message) { } + public BadHttpRequestException(string message, System.Exception innerException) { } + public BadHttpRequestException(string message, int statusCode) { } + public BadHttpRequestException(string message, int statusCode, System.Exception innerException) { } + public int StatusCode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + } public abstract partial class ConnectionInfo { protected ConnectionInfo() { } diff --git a/src/Http/Http.Abstractions/src/BadHttpRequestException.cs b/src/Http/Http.Abstractions/src/BadHttpRequestException.cs new file mode 100644 index 0000000000..1e8a0bf096 --- /dev/null +++ b/src/Http/Http.Abstractions/src/BadHttpRequestException.cs @@ -0,0 +1,60 @@ +using System; +using System.IO; + +namespace Microsoft.AspNetCore.Http +{ + /// + /// Represents an HTTP request error + /// + public class BadHttpRequestException : IOException + { + /// + /// Initializes a new instance of the class. + /// + /// The message to associate with this exception. + /// The HTTP status code to associate with this exception. + public BadHttpRequestException(string message, int statusCode) + : base(message) + { + StatusCode = statusCode; + } + + /// + /// Initializes a new instance of the class with the set to 400 Bad Request. + /// + /// The message to associate with this exception + public BadHttpRequestException(string message) + : base(message) + { + StatusCode = StatusCodes.Status400BadRequest; + } + + /// + /// Initializes a new instance of the class. + /// + /// The message to associate with this exception. + /// The HTTP status code to associate with this exception. + /// The inner exception to associate with this exception + public BadHttpRequestException(string message, int statusCode, Exception innerException) + : base(message, innerException) + { + StatusCode = statusCode; + } + + /// + /// Initializes a new instance of the class with the set to 400 Bad Request. + /// + /// The message to associate with this exception + /// The inner exception to associate with this exception + public BadHttpRequestException(string message, Exception innerException) + : base(message, innerException) + { + StatusCode = StatusCodes.Status400BadRequest; + } + + /// + /// Gets the HTTP status code for this exception. + /// + public int StatusCode { get; } + } +} diff --git a/src/Servers/IIS/IIS/ref/Microsoft.AspNetCore.Server.IIS.netcoreapp.cs b/src/Servers/IIS/IIS/ref/Microsoft.AspNetCore.Server.IIS.netcoreapp.cs index 479bfe8e6c..a32e60734b 100644 --- a/src/Servers/IIS/IIS/ref/Microsoft.AspNetCore.Server.IIS.netcoreapp.cs +++ b/src/Servers/IIS/IIS/ref/Microsoft.AspNetCore.Server.IIS.netcoreapp.cs @@ -21,10 +21,11 @@ namespace Microsoft.AspNetCore.Hosting } namespace Microsoft.AspNetCore.Server.IIS { - public sealed partial class BadHttpRequestException : System.IO.IOException + [System.ObsoleteAttribute("Moved to Microsoft.AspNetCore.Http.BadHttpRequestException")] + public sealed partial class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { - internal BadHttpRequestException() { } - public int StatusCode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + internal BadHttpRequestException() : base (default(string), default(int)) { } + public new int StatusCode { get { throw null; } } } public static partial class HttpContextExtensions { diff --git a/src/Servers/IIS/IIS/src/BadHttpRequestException.cs b/src/Servers/IIS/IIS/src/BadHttpRequestException.cs index 527692f89c..2abefae9e9 100644 --- a/src/Servers/IIS/IIS/src/BadHttpRequestException.cs +++ b/src/Servers/IIS/IIS/src/BadHttpRequestException.cs @@ -1,44 +1,24 @@ // 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.IO; using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Http; namespace Microsoft.AspNetCore.Server.IIS { - public sealed class BadHttpRequestException : IOException + [Obsolete("Moved to Microsoft.AspNetCore.Http.BadHttpRequestException")] + public sealed class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { - private BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason) - : base(message) + internal BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason) + : base(message, statusCode) { - StatusCode = statusCode; Reason = reason; } - public int StatusCode { get; } + public new int StatusCode { get => base.StatusCode; } internal RequestRejectionReason Reason { get; } - - internal static void Throw(RequestRejectionReason reason) - { - throw GetException(reason); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - internal static BadHttpRequestException GetException(RequestRejectionReason reason) - { - BadHttpRequestException ex; - switch (reason) - { - case RequestRejectionReason.RequestBodyTooLarge: - ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTooLarge, StatusCodes.Status413PayloadTooLarge, reason); - break; - default: - ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); - break; - } - return ex; - } } } diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs index 5f831eb01a..60d098bc11 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.IO.cs @@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core if (_consumedBytes > MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + IISBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } var result = await _bodyInputPipe.Writer.FlushAsync(); diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.Log.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.Log.cs index 4f84786cf0..8a28ecc08a 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.Log.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.Log.cs @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core _unexpectedError(logger, className, methodName, ex); } - public static void ConnectionBadRequest(ILogger logger, string connectionId, BadHttpRequestException ex) + public static void ConnectionBadRequest(ILogger logger, string connectionId, Microsoft.AspNetCore.Http.BadHttpRequestException ex) { _connectionBadRequest(logger, connectionId, ex.Message, ex); } diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContext.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContext.cs index 74f0cbae6b..5103ae871d 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContext.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContext.cs @@ -26,6 +26,8 @@ using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.IIS.Core { + using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; + internal abstract partial class IISHttpContext : NativeRequestContext, IThreadPoolWorkItem, IDisposable { private const int MinAllocBufferSize = 2048; @@ -293,7 +295,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core if (RequestHeaders.ContentLength > MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + IISBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } HasStartedConsumingRequestBody = true; diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs b/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs index 060f105233..cfdc20b225 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpContextOfT.cs @@ -11,6 +11,8 @@ using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.IIS.Core { + using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; + internal class IISHttpContextOfT : IISHttpContext { private readonly IHttpApplication _application; diff --git a/src/Servers/IIS/IIS/src/IISBadHttpRequestException.cs b/src/Servers/IIS/IIS/src/IISBadHttpRequestException.cs new file mode 100644 index 0000000000..3ee8ee42aa --- /dev/null +++ b/src/Servers/IIS/IIS/src/IISBadHttpRequestException.cs @@ -0,0 +1,36 @@ +// 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.IO; +using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Http; + +namespace Microsoft.AspNetCore.Server.IIS +{ + internal static class IISBadHttpRequestException + { + internal static void Throw(RequestRejectionReason reason) + { + throw GetException(reason); + } + + [MethodImpl(MethodImplOptions.NoInlining)] +#pragma warning disable CS0618 // Type or member is obsolete + internal static BadHttpRequestException GetException(RequestRejectionReason reason) + { + BadHttpRequestException ex; + switch (reason) + { + case RequestRejectionReason.RequestBodyTooLarge: + ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTooLarge, StatusCodes.Status413PayloadTooLarge, reason); + break; + default: + ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); + break; + } + return ex; + } +#pragma warning restore CS0618 // Type or member is obsolete + } +} diff --git a/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs b/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs index 1f46ed1b4b..0eb92e4ec7 100644 --- a/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs +++ b/src/Servers/IIS/IIS/test/IIS.Tests/MaxRequestBodySizeTests.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Server.IIS.FunctionalTests; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging.Testing; using Xunit; +using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; namespace IIS.Tests { @@ -24,6 +25,7 @@ namespace IIS.Tests var globalMaxRequestBodySize = 0x100000000; BadHttpRequestException exception = null; + using (var testServer = await TestServer.Create( async ctx => { @@ -60,6 +62,7 @@ namespace IIS.Tests var perRequestMaxRequestBodySize = 0x100; BadHttpRequestException exception = null; + using (var testServer = await TestServer.Create( async ctx => { @@ -71,6 +74,7 @@ namespace IIS.Tests await ctx.Request.Body.ReadAsync(new byte[2000]); } + catch (BadHttpRequestException ex) { exception = ex; @@ -266,6 +270,7 @@ namespace IIS.Tests var maxRequestSize = 0x1000; BadHttpRequestException exception = null; + using (var testServer = await TestServer.Create( async ctx => { @@ -307,13 +312,14 @@ namespace IIS.Tests { BadHttpRequestException requestRejectedEx1 = null; BadHttpRequestException requestRejectedEx2 = null; + using (var testServer = await TestServer.Create( async ctx => { var buffer = new byte[1]; - requestRejectedEx1 = await Assert.ThrowsAsync( + requestRejectedEx1 = await Assert.ThrowsAnyAsync( async () => await ctx.Request.Body.ReadAsync(buffer, 0, 1)); - requestRejectedEx2 = await Assert.ThrowsAsync( + requestRejectedEx2 = await Assert.ThrowsAnyAsync( async () => await ctx.Request.Body.ReadAsync(buffer, 0, 1)); throw requestRejectedEx2; }, LoggerFactory, new IISServerOptions { MaxRequestBodySize = 0 })) diff --git a/src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp.cs b/src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp.cs index cfbd7ab1e2..7de1a0907e 100644 --- a/src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp.cs +++ b/src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp.cs @@ -62,10 +62,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel } namespace Microsoft.AspNetCore.Server.Kestrel.Core { - public sealed partial class BadHttpRequestException : System.IO.IOException + [System.ObsoleteAttribute("Moved to Microsoft.AspNetCore.Http.BadHttpRequestException")] + public sealed partial class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { - internal BadHttpRequestException() { } - public int StatusCode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + internal BadHttpRequestException() : base (default(string), default(int)) { } + public new int StatusCode { get { throw null; } } } public partial class Http2Limits { diff --git a/src/Servers/Kestrel/Core/src/BadHttpRequestException.cs b/src/Servers/Kestrel/Core/src/BadHttpRequestException.cs index 16f7ab0fce..d68eff9a45 100644 --- a/src/Servers/Kestrel/Core/src/BadHttpRequestException.cs +++ b/src/Servers/Kestrel/Core/src/BadHttpRequestException.cs @@ -1,26 +1,23 @@ // 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.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using Microsoft.AspNetCore.Http; +using System; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Server.Kestrel.Core { - public sealed class BadHttpRequestException : IOException + [Obsolete("Moved to Microsoft.AspNetCore.Http.BadHttpRequestException")] + public sealed class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { - private BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason) + internal BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason) : this(message, statusCode, reason, null) { } - private BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason, HttpMethod? requiredMethod) - : base(message) + internal BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason, HttpMethod? requiredMethod) + : base(message, statusCode) { - StatusCode = statusCode; Reason = reason; if (requiredMethod.HasValue) @@ -29,151 +26,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core } } - public int StatusCode { get; } + public new int StatusCode { get => base.StatusCode; } internal StringValues AllowedHeader { get; } internal RequestRejectionReason Reason { get; } - - [StackTraceHidden] - internal static void Throw(RequestRejectionReason reason) - { - throw GetException(reason); - } - - [StackTraceHidden] - internal static void Throw(RequestRejectionReason reason, HttpMethod method) - => throw GetException(reason, method.ToString().ToUpperInvariant()); - - [MethodImpl(MethodImplOptions.NoInlining)] - internal static BadHttpRequestException GetException(RequestRejectionReason reason) - { - BadHttpRequestException ex; - switch (reason) - { - case RequestRejectionReason.InvalidRequestHeadersNoCRLF: - ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidRequestHeadersNoCRLF, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidRequestLine: - ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidRequestLine, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.MalformedRequestInvalidHeaders: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MalformedRequestInvalidHeaders, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.MultipleContentLengths: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MultipleContentLengths, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.UnexpectedEndOfRequestContent: - ex = new BadHttpRequestException(CoreStrings.BadRequest_UnexpectedEndOfRequestContent, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.BadChunkSuffix: - ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkSuffix, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.BadChunkSizeData: - ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkSizeData, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.ChunkedRequestIncomplete: - ex = new BadHttpRequestException(CoreStrings.BadRequest_ChunkedRequestIncomplete, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidCharactersInHeaderName: - ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidCharactersInHeaderName, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.RequestLineTooLong: - ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestLineTooLong, StatusCodes.Status414UriTooLong, reason); - break; - case RequestRejectionReason.HeadersExceedMaxTotalSize: - ex = new BadHttpRequestException(CoreStrings.BadRequest_HeadersExceedMaxTotalSize, StatusCodes.Status431RequestHeaderFieldsTooLarge, reason); - break; - case RequestRejectionReason.TooManyHeaders: - ex = new BadHttpRequestException(CoreStrings.BadRequest_TooManyHeaders, StatusCodes.Status431RequestHeaderFieldsTooLarge, reason); - break; - case RequestRejectionReason.RequestBodyTooLarge: - ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTooLarge, StatusCodes.Status413PayloadTooLarge, reason); - break; - case RequestRejectionReason.RequestHeadersTimeout: - ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestHeadersTimeout, StatusCodes.Status408RequestTimeout, reason); - break; - case RequestRejectionReason.RequestBodyTimeout: - ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTimeout, StatusCodes.Status408RequestTimeout, reason); - break; - case RequestRejectionReason.OptionsMethodRequired: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MethodNotAllowed, StatusCodes.Status405MethodNotAllowed, reason, HttpMethod.Options); - break; - case RequestRejectionReason.ConnectMethodRequired: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MethodNotAllowed, StatusCodes.Status405MethodNotAllowed, reason, HttpMethod.Connect); - break; - case RequestRejectionReason.MissingHostHeader: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MissingHostHeader, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.MultipleHostHeaders: - ex = new BadHttpRequestException(CoreStrings.BadRequest_MultipleHostHeaders, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidHostHeader: - ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidHostHeader, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.UpgradeRequestCannotHavePayload: - ex = new BadHttpRequestException(CoreStrings.BadRequest_UpgradeRequestCannotHavePayload, StatusCodes.Status400BadRequest, reason); - break; - default: - ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); - break; - } - return ex; - } - - [StackTraceHidden] - internal static void Throw(RequestRejectionReason reason, string detail) - { - throw GetException(reason, detail); - } - - [StackTraceHidden] - internal static void Throw(RequestRejectionReason reason, StringValues detail) - { - throw GetException(reason, detail.ToString()); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - internal static BadHttpRequestException GetException(RequestRejectionReason reason, string detail) - { - BadHttpRequestException ex; - switch (reason) - { - case RequestRejectionReason.TlsOverHttpError: - ex = new BadHttpRequestException(CoreStrings.HttpParserTlsOverHttpError, StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidRequestLine: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestLine_Detail(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidRequestTarget: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidRequestHeader: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestHeader_Detail(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidContentLength: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidContentLength_Detail(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.UnrecognizedHTTPVersion: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_UnrecognizedHTTPVersion(detail), StatusCodes.Status505HttpVersionNotsupported, reason); - break; - case RequestRejectionReason.FinalTransferCodingNotChunked: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_FinalTransferCodingNotChunked(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.LengthRequired: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_LengthRequired(detail), StatusCodes.Status411LengthRequired, reason); - break; - case RequestRejectionReason.LengthRequiredHttp10: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_LengthRequiredHttp10(detail), StatusCodes.Status400BadRequest, reason); - break; - case RequestRejectionReason.InvalidHostHeader: - ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidHostHeader_Detail(detail), StatusCodes.Status400BadRequest, reason); - break; - default: - ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); - break; - } - return ex; - } } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs index 9c87b3697e..2a2c01051d 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs @@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (_context.RequestTimedOut) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); } var readableBuffer = result.Buffer; @@ -373,7 +373,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http } // At this point, 10 bytes have been consumed which is enough to parse the max value "7FFFFFFF\r\n". - BadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData); } private void ParseExtension(ReadOnlySequence buffer, out SequencePosition consumed, out SequencePosition examined) @@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http } else { - BadHttpRequestException.Throw(RequestRejectionReason.BadChunkSuffix); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.BadChunkSuffix); } } @@ -528,7 +528,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http throw new IOException(CoreStrings.BadRequest_BadChunkSizeData, ex); } - BadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData); + return -1; // can't happen, but compiler complains } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs index 832d48cdce..ef77a1f396 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs @@ -204,7 +204,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (!_parser.ParseRequestLine(new Http1ParsingHandler(this), trimmedBuffer, out consumed, out examined)) { // We read the maximum allowed but didn't complete the start line. - BadHttpRequestException.Throw(RequestRejectionReason.RequestLineTooLong); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestLineTooLong); } return true; @@ -261,7 +261,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (!result) { // We read the maximum allowed but didn't complete the headers. - BadHttpRequestException.Throw(RequestRejectionReason.HeadersExceedMaxTotalSize); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.HeadersExceedMaxTotalSize); } TimeoutControl.CancelTimeout(); @@ -424,7 +424,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http // requests (https://tools.ietf.org/html/rfc7231#section-4.3.6). if (method != HttpMethod.Connect) { - BadHttpRequestException.Throw(RequestRejectionReason.ConnectMethodRequired); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.ConnectMethodRequired); } // When making a CONNECT request to establish a tunnel through one or @@ -468,7 +468,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http // OPTIONS request (https://tools.ietf.org/html/rfc7231#section-4.3.7). if (method != HttpMethod.Options) { - BadHttpRequestException.Throw(RequestRejectionReason.OptionsMethodRequired); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.OptionsMethodRequired); } RawTarget = Asterisk; @@ -555,11 +555,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { return; } - BadHttpRequestException.Throw(RequestRejectionReason.MissingHostHeader); + + KestrelBadHttpRequestException.Throw(RequestRejectionReason.MissingHostHeader); } else if (hostCount > 1) { - BadHttpRequestException.Throw(RequestRejectionReason.MultipleHostHeaders); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.MultipleHostHeaders); } else if (_requestTargetForm != HttpRequestTarget.OriginForm) { @@ -568,7 +569,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http } else if (!HttpUtilities.IsHostHeaderValid(hostText)) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } @@ -578,7 +579,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (hostText != RawTarget) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } else if (_requestTargetForm == HttpRequestTarget.AbsoluteForm) @@ -595,14 +596,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (!_absoluteRequestTarget.IsDefaultPort || hostText != _absoluteRequestTarget.Authority + ":" + _absoluteRequestTarget.Port.ToString(CultureInfo.InvariantCulture)) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } } if (!HttpUtilities.IsHostHeaderValid(hostText)) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidHostHeader, hostText); } } @@ -655,7 +656,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (_requestProcessingStatus == RequestProcessingStatus.ParsingHeaders) { - BadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); } throw; } @@ -672,10 +673,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http endConnection = true; return true; case RequestProcessingStatus.ParsingRequestLine: - BadHttpRequestException.Throw(RequestRejectionReason.InvalidRequestLine); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidRequestLine); break; case RequestProcessingStatus.ParsingHeaders: - BadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.MalformedRequestInvalidHeaders); break; } } @@ -690,7 +691,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { // In this case, there is an ongoing request but the start line/header parsing has timed out, so send // a 408 response. - BadHttpRequestException.Throw(RequestRejectionReason.RequestHeadersTimeout); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestHeadersTimeout); } endConnection = false; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ContentLengthMessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ContentLengthMessageBody.cs index 7ef9a167a4..b0d1bf7846 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ContentLengthMessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ContentLengthMessageBody.cs @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http // which is unknown to StartTimingReadAsync. if (_context.RequestTimedOut) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); } try @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (_context.RequestTimedOut) { ResetReadingState(); - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTimeout); } if (_readResult.IsCompleted) @@ -234,7 +234,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (_contentLength > _context.MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1MessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1MessageBody.cs index c5993cd7cc..282e665db8 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1MessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1MessageBody.cs @@ -11,6 +11,8 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { + using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; + internal abstract class Http1MessageBody : MessageBody { protected readonly Http1Connection _context; @@ -31,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http // closing the connection without a response as expected. _context.OnInputOrOutputCompleted(); - BadHttpRequestException.Throw(RequestRejectionReason.UnexpectedEndOfRequestContent); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.UnexpectedEndOfRequestContent); } public abstract bool TryReadInternal(out ReadResult readResult); @@ -87,7 +89,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http AdvanceTo(result.Buffer.End); } while (!result.IsCompleted); } - catch (BadHttpRequestException ex) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException ex) { _context.SetBadRequestState(ex); } @@ -130,7 +132,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (headers.HeaderTransferEncoding.Count > 0 || (headers.ContentLength.HasValue && headers.ContentLength.Value != 0)) { - BadHttpRequestException.Throw(RequestRejectionReason.UpgradeRequestCannotHavePayload); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.UpgradeRequestCannotHavePayload); } context.OnTrailersComplete(); // No trailers for these. @@ -150,7 +152,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http // status code and then close the connection. if (transferCoding != TransferCoding.Chunked) { - BadHttpRequestException.Throw(RequestRejectionReason.FinalTransferCodingNotChunked, transferEncoding); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.FinalTransferCodingNotChunked, transferEncoding); } // TODO may push more into the wrapper rather than just calling into the message body @@ -175,7 +177,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (context.Method == HttpMethod.Post || context.Method == HttpMethod.Put) { var requestRejectionReason = httpVersion == HttpVersion.Http11 ? RequestRejectionReason.LengthRequired : RequestRejectionReason.LengthRequiredHttp10; - BadHttpRequestException.Throw(requestRejectionReason, context.Method); + KestrelBadHttpRequestException.Throw(requestRejectionReason, context.Method); } context.OnTrailersComplete(); // No trailers for these. diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs index ff905ca079..d34dc047c2 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs @@ -11,6 +11,8 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { + using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; + public class HttpParser : IHttpParser where TRequestHandler : IHttpHeadersHandler, IHttpRequestLineHandler { private readonly bool _showErrorDetails; @@ -225,7 +227,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http Debug.Assert(readAhead == 0 || readAhead == 2); // Headers don't end in CRLF line. - BadHttpRequestException.Throw(RequestRejectionReason.InvalidRequestHeadersNoCRLF); + + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidRequestHeadersNoCRLF); } var length = 0; @@ -451,7 +454,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http [MethodImpl(MethodImplOptions.NoInlining)] private unsafe BadHttpRequestException GetInvalidRequestException(RequestRejectionReason reason, byte* detail, int length) - => BadHttpRequestException.GetException( + => KestrelBadHttpRequestException.GetException( reason, _showErrorDetails ? new Span(detail, length).GetAsciiStringEscaped(Constants.MaxExceptionDetailSize) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs index 6efacd2e74..cfe97f0f1e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs @@ -26,6 +26,8 @@ using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { + using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; + internal abstract partial class HttpProtocol : IHttpResponseControl { private static readonly byte[] _bytesConnectionClose = Encoding.ASCII.GetBytes("\r\nConnection: close"); @@ -513,7 +515,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http _requestHeadersParsed++; if (_requestHeadersParsed > ServerOptions.Limits.MaxRequestHeaderCount) { - BadHttpRequestException.Throw(RequestRejectionReason.TooManyHeaders); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.TooManyHeaders); } HttpRequestHeaders.Append(name, value); @@ -525,7 +527,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http _requestHeadersParsed++; if (_requestHeadersParsed > ServerOptions.Limits.MaxRequestHeaderCount) { - BadHttpRequestException.Throw(RequestRejectionReason.TooManyHeaders); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.TooManyHeaders); } string key = name.GetHeaderName(); @@ -1215,9 +1217,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { SetErrorResponseHeaders(ex.StatusCode); - if (!StringValues.IsNullOrEmpty(ex.AllowedHeader)) +#pragma warning disable CS0618 // Type or member is obsolete + if (ex is Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException kestrelEx && !StringValues.IsNullOrEmpty(kestrelEx.AllowedHeader)) +#pragma warning restore CS0618 // Type or member is obsolete { - HttpResponseHeaders.HeaderAllow = ex.AllowedHeader; + HttpResponseHeaders.HeaderAllow = kestrelEx.AllowedHeader; } } @@ -1271,7 +1275,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http [MethodImpl(MethodImplOptions.NoInlining)] private BadHttpRequestException GetInvalidRequestTargetException(Span target) - => BadHttpRequestException.GetException( + => KestrelBadHttpRequestException.GetException( RequestRejectionReason.InvalidRequestTarget, Log.IsEnabled(LogLevel.Information) ? target.GetAsciiStringEscaped(Constants.MaxExceptionDetailSize) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs index a5e78a4442..95f5c69e79 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs @@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (!HeaderUtilities.TryParseNonNegativeInt64(value, out var parsed)) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value); } return parsed; @@ -76,14 +76,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { if (_contentLength.HasValue) { - BadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths); } if (!Utf8Parser.TryParse(value, out long parsed, out var consumed) || parsed < 0 || consumed != value.Length) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetRequestHeaderStringNonNullCharacters(UseLatin1)); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetRequestHeaderStringNonNullCharacters(UseLatin1)); } _contentLength = parsed; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/MessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/MessageBody.cs index e97712f0ae..4f55f3de74 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/MessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/MessageBody.cs @@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http if (_consumedBytes > _context.MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs index acf81b3e12..3bc267e8c7 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs @@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 public void HandleRequestHeadersTimeout() { - Log.ConnectionBadRequest(ConnectionId, BadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); + Log.ConnectionBadRequest(ConnectionId, KestrelBadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); Abort(new ConnectionAbortedException(CoreStrings.BadRequest_RequestHeadersTimeout)); } @@ -1197,7 +1197,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 _currentHeadersStream.OnHeader(name, value); } } - catch (BadHttpRequestException bre) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException bre) { throw new Http2ConnectionErrorException(bre.Message, Http2ErrorCode.PROTOCOL_ERROR); } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2MessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2MessageBody.cs index dd62d69cbb..3d1dead1b9 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2MessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2MessageBody.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 // Note ContentLength or MaxRequestBodySize may be null if (_context.RequestHeaders.ContentLength > _context.MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3ControlStream.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3ControlStream.cs index a75d8bc69a..0c89d21c0d 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3ControlStream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3ControlStream.cs @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3 public void HandleRequestHeadersTimeout() { - //Log.ConnectionBadRequest(ConnectionId, BadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); + //Log.ConnectionBadRequest(ConnectionId, KestrelBadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); Abort(new ConnectionAbortedException(CoreStrings.BadRequest_RequestHeadersTimeout)); } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3MessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3MessageBody.cs index 5af5f8df47..77efd60e7b 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3MessageBody.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3MessageBody.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3 // Note ContentLength or MaxRequestBodySize may be null if (_context.RequestHeaders.ContentLength > _context.MaxRequestBodySize) { - BadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.RequestBodyTooLarge); } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs index 6518d00afd..576443150c 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs @@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3 base.OnHeader(name, value); } } - catch (BadHttpRequestException bre) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException bre) { throw new Http3StreamErrorException(bre.Message, Http3ErrorCode.ProtocolError); } @@ -293,7 +293,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3 public void HandleRequestHeadersTimeout() { - Log.ConnectionBadRequest(ConnectionId, BadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); + Log.ConnectionBadRequest(ConnectionId, KestrelBadHttpRequestException.GetException(RequestRejectionReason.RequestHeadersTimeout)); Abort(new ConnectionAbortedException(CoreStrings.BadRequest_RequestHeadersTimeout), Http3ErrorCode.RequestRejected); } diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpUtilities.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpUtilities.cs index 70fa7f00b3..9e21228c6d 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpUtilities.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpUtilities.cs @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure // in the string if (!StringUtilities.TryGetAsciiString((byte*)state.ToPointer(), output, buffer.Length)) { - BadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName); + KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName); } } } diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs index cd441ae3a2..54a8392fae 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure void NotAllConnectionsClosedGracefully(); - void ConnectionBadRequest(string connectionId, BadHttpRequestException ex); + void ConnectionBadRequest(string connectionId, Microsoft.AspNetCore.Http.BadHttpRequestException ex); void ApplicationError(string connectionId, string traceIdentifier, Exception ex); diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs index f89732a704..6edaf7b599 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs @@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure _notAllConnectionsClosedGracefully(_logger, null); } - public virtual void ConnectionBadRequest(string connectionId, BadHttpRequestException ex) + public virtual void ConnectionBadRequest(string connectionId, Microsoft.AspNetCore.Http.BadHttpRequestException ex) { _connectionBadRequest(_logger, connectionId, ex.Message, ex); } diff --git a/src/Servers/Kestrel/Core/src/KestralBadHttpRequestException.cs b/src/Servers/Kestrel/Core/src/KestralBadHttpRequestException.cs new file mode 100644 index 0000000000..0921e41e77 --- /dev/null +++ b/src/Servers/Kestrel/Core/src/KestralBadHttpRequestException.cs @@ -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.Diagnostics; +using System.Runtime.CompilerServices; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; +using Microsoft.Extensions.Primitives; + +namespace Microsoft.AspNetCore.Server.Kestrel.Core +{ + internal static class KestrelBadHttpRequestException + { + [StackTraceHidden] + internal static void Throw(RequestRejectionReason reason) + { + throw GetException(reason); + } + + [StackTraceHidden] + internal static void Throw(RequestRejectionReason reason, HttpMethod method) + => throw GetException(reason, method.ToString().ToUpperInvariant()); + + [MethodImpl(MethodImplOptions.NoInlining)] +#pragma warning disable CS0618 // Type or member is obsolete + internal static BadHttpRequestException GetException(RequestRejectionReason reason) + { + BadHttpRequestException ex; + switch (reason) + { + case RequestRejectionReason.InvalidRequestHeadersNoCRLF: + ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidRequestHeadersNoCRLF, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidRequestLine: + ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidRequestLine, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.MalformedRequestInvalidHeaders: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MalformedRequestInvalidHeaders, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.MultipleContentLengths: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MultipleContentLengths, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.UnexpectedEndOfRequestContent: + ex = new BadHttpRequestException(CoreStrings.BadRequest_UnexpectedEndOfRequestContent, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.BadChunkSuffix: + ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkSuffix, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.BadChunkSizeData: + ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkSizeData, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.ChunkedRequestIncomplete: + ex = new BadHttpRequestException(CoreStrings.BadRequest_ChunkedRequestIncomplete, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidCharactersInHeaderName: + ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidCharactersInHeaderName, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.RequestLineTooLong: + ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestLineTooLong, StatusCodes.Status414UriTooLong, reason); + break; + case RequestRejectionReason.HeadersExceedMaxTotalSize: + ex = new BadHttpRequestException(CoreStrings.BadRequest_HeadersExceedMaxTotalSize, StatusCodes.Status431RequestHeaderFieldsTooLarge, reason); + break; + case RequestRejectionReason.TooManyHeaders: + ex = new BadHttpRequestException(CoreStrings.BadRequest_TooManyHeaders, StatusCodes.Status431RequestHeaderFieldsTooLarge, reason); + break; + case RequestRejectionReason.RequestBodyTooLarge: + ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTooLarge, StatusCodes.Status413PayloadTooLarge, reason); + break; + case RequestRejectionReason.RequestHeadersTimeout: + ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestHeadersTimeout, StatusCodes.Status408RequestTimeout, reason); + break; + case RequestRejectionReason.RequestBodyTimeout: + ex = new BadHttpRequestException(CoreStrings.BadRequest_RequestBodyTimeout, StatusCodes.Status408RequestTimeout, reason); + break; + case RequestRejectionReason.OptionsMethodRequired: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MethodNotAllowed, StatusCodes.Status405MethodNotAllowed, reason, HttpMethod.Options); + break; + case RequestRejectionReason.ConnectMethodRequired: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MethodNotAllowed, StatusCodes.Status405MethodNotAllowed, reason, HttpMethod.Connect); + break; + case RequestRejectionReason.MissingHostHeader: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MissingHostHeader, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.MultipleHostHeaders: + ex = new BadHttpRequestException(CoreStrings.BadRequest_MultipleHostHeaders, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidHostHeader: + ex = new BadHttpRequestException(CoreStrings.BadRequest_InvalidHostHeader, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.UpgradeRequestCannotHavePayload: + ex = new BadHttpRequestException(CoreStrings.BadRequest_UpgradeRequestCannotHavePayload, StatusCodes.Status400BadRequest, reason); + break; + default: + ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); + break; + } + return ex; + } +#pragma warning restore CS0618 // Type or member is obsolete + + [StackTraceHidden] + internal static void Throw(RequestRejectionReason reason, string detail) + { + throw GetException(reason, detail); + } + + [StackTraceHidden] + internal static void Throw(RequestRejectionReason reason, StringValues detail) + { + throw GetException(reason, detail.ToString()); + } + +#pragma warning disable CS0618 // Type or member is obsolete + [MethodImpl(MethodImplOptions.NoInlining)] + internal static BadHttpRequestException GetException(RequestRejectionReason reason, string detail) + { + BadHttpRequestException ex; + switch (reason) + { + case RequestRejectionReason.TlsOverHttpError: + ex = new BadHttpRequestException(CoreStrings.HttpParserTlsOverHttpError, StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidRequestLine: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestLine_Detail(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidRequestTarget: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestTarget_Detail(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidRequestHeader: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidRequestHeader_Detail(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidContentLength: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidContentLength_Detail(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.UnrecognizedHTTPVersion: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_UnrecognizedHTTPVersion(detail), StatusCodes.Status505HttpVersionNotsupported, reason); + break; + case RequestRejectionReason.FinalTransferCodingNotChunked: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_FinalTransferCodingNotChunked(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.LengthRequired: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_LengthRequired(detail), StatusCodes.Status411LengthRequired, reason); + break; + case RequestRejectionReason.LengthRequiredHttp10: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_LengthRequiredHttp10(detail), StatusCodes.Status400BadRequest, reason); + break; + case RequestRejectionReason.InvalidHostHeader: + ex = new BadHttpRequestException(CoreStrings.FormatBadRequest_InvalidHostHeader_Detail(detail), StatusCodes.Status400BadRequest, reason); + break; + default: + ex = new BadHttpRequestException(CoreStrings.BadRequest, StatusCodes.Status400BadRequest, reason); + break; + } + return ex; + } +#pragma warning restore CS0618 // Type or member is obsolete + } +} diff --git a/src/Servers/Kestrel/Core/test/Http1ConnectionTests.cs b/src/Servers/Kestrel/Core/test/Http1ConnectionTests.cs index 0992626a80..f60e3d9f91 100644 --- a/src/Servers/Kestrel/Core/test/Http1ConnectionTests.cs +++ b/src/Servers/Kestrel/Core/test/Http1ConnectionTests.cs @@ -127,7 +127,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"{headerLine}\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => _http1Connection.TakeMessageHeaders(readableBuffer, trailers: false, out _consumed, out _examined)); +#pragma warning restore CS0618 // Type or member is obsolete _transport.Input.AdvanceTo(_consumed, _examined); Assert.Equal(CoreStrings.BadRequest_HeadersExceedMaxTotalSize, exception.Message); @@ -143,7 +145,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"{headerLines}\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => _http1Connection.TakeMessageHeaders(readableBuffer, trailers: false, out _consumed, out _examined)); +#pragma warning restore CS0618 // Type or member is obsolete _transport.Input.AdvanceTo(_consumed, _examined); Assert.Equal(CoreStrings.BadRequest_TooManyHeaders, exception.Message); @@ -438,7 +442,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(requestLineBytes); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); +#pragma warning restore CS0618 // Type or member is obsolete _transport.Input.AdvanceTo(_consumed, _examined); Assert.Equal(CoreStrings.BadRequest_RequestLineTooLong, exception.Message); @@ -452,7 +458,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"GET {target} HTTP/1.1\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -466,7 +474,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"GET {target} HTTP/1.1\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -482,7 +492,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes(requestLine)); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -498,7 +510,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"GET {target} HTTP/1.1\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -514,7 +528,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes(requestLine)); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -529,7 +545,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes(requestLine)); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -774,7 +792,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"GET /%00 HTTP/1.1\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete _http1Connection.TakeStartLine(readableBuffer, out _consumed, out _examined)); _transport.Input.AdvanceTo(_consumed, _examined); @@ -934,7 +954,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests { _http1Connection.HttpVersion = "HTTP/1.0"; _http1Connection.RequestHeaders[HeaderNames.Host] = "a=b"; +#pragma warning disable CS0618 // Type or member is obsolete var ex = Assert.Throws(() => _http1Connection.EnsureHostHeaderExists()); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(CoreStrings.FormatBadRequest_InvalidHostHeader_Detail("a=b"), ex.Message); } @@ -943,7 +965,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests { _http1Connection.HttpVersion = "HTTP/1.1"; _http1Connection.RequestHeaders[HeaderNames.Host] = "a=b"; +#pragma warning disable CS0618 // Type or member is obsolete var ex = Assert.Throws(() => _http1Connection.EnsureHostHeaderExists()); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(CoreStrings.FormatBadRequest_InvalidHostHeader_Detail("a=b"), ex.Message); } diff --git a/src/Servers/Kestrel/Core/test/HttpParserTests.cs b/src/Servers/Kestrel/Core/test/HttpParserTests.cs index 1b2646d16b..b8029aa403 100644 --- a/src/Servers/Kestrel/Core/test/HttpParserTests.cs +++ b/src/Servers/Kestrel/Core/test/HttpParserTests.cs @@ -90,11 +90,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes(requestLine)); var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestLine_Detail(requestLine.EscapeNonPrintable()), exception.Message); - Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode); + Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); } [Theory] @@ -112,11 +114,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes(requestLine)); var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestLine_Detail(method.EscapeNonPrintable() + @" / HTTP/1.1\x0D\x0A"), exception.Message); - Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode); + Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); } [Theory] @@ -134,11 +138,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes(requestLine)); var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(CoreStrings.FormatBadRequest_UnrecognizedHTTPVersion(httpVersion), exception.Message); - Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode); + Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, exception.StatusCode); } [Theory] @@ -328,7 +334,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes(rawHeaders)); var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete { var reader = new SequenceReader(buffer); parser.ParseHeaders(requestHandler, ref reader); @@ -352,25 +360,31 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n")); var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal("Invalid request line: ''", exception.Message); - Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode); + Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); // Unrecognized HTTP version buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n")); +#pragma warning disable CS0618 // Type or member is obsolete exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(CoreStrings.FormatBadRequest_UnrecognizedHTTPVersion(string.Empty), exception.Message); - Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode); + Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, exception.StatusCode); // Invalid request header buffer = new ReadOnlySequence(Encoding.ASCII.GetBytes("Header: value\n\r\n")); +#pragma warning disable CS0618 // Type or member is obsolete exception = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete { var reader = new SequenceReader(buffer); parser.ParseHeaders(requestHandler, ref reader); @@ -404,7 +418,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests var requestHandler = new RequestHandler(); +#pragma warning disable CS0618 // Type or member is obsolete var badHttpRequestException = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete { parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined); }); diff --git a/src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs b/src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs index d87f1f814f..098f6fc0ed 100644 --- a/src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs +++ b/src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs @@ -308,7 +308,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests const string key = "\u00141\u00F3d\017c"; var encoding = Encoding.GetEncoding("iso-8859-1"); +#pragma warning disable CS0618 // Type or member is obsolete var exception = Assert.Throws( +#pragma warning restore CS0618 // Type or member is obsolete () => headers.Append(encoding.GetBytes(key), Encoding.ASCII.GetBytes("value"))); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); } diff --git a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs index b44caa62d4..5ea87c1b6c 100644 --- a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs +++ b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs @@ -221,7 +221,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Add("g"); input.Add("g"); +#pragma warning disable CS0618 // Type or member is obsolete await Assert.ThrowsAsync(() => task); +#pragma warning restore CS0618 // Type or member is obsolete await body.StopAsync(); } @@ -247,7 +249,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Add(i.ToString()); } +#pragma warning disable CS0618 // Type or member is obsolete await Assert.ThrowsAsync(() => task); +#pragma warning restore CS0618 // Type or member is obsolete await body.StopAsync(); } @@ -286,7 +290,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Add("\r"); input.Add("n"); +#pragma warning disable CS0618 // Type or member is obsolete await Assert.ThrowsAsync(() => task); +#pragma warning restore CS0618 // Type or member is obsolete await body.StopAsync(); } @@ -388,7 +394,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Add("012345678\r"); var buffer = new byte[1024]; +#pragma warning disable CS0618 // Type or member is obsolete var ex = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete await stream.ReadAsync(buffer, 0, buffer.Length)); Assert.Equal(CoreStrings.BadRequest_BadChunkSizeData, ex.Message); @@ -536,7 +544,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests { using (var input = new TestInput()) { +#pragma warning disable CS0618 // Type or member is obsolete var ex = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders { HeaderTransferEncoding = "chunked, not-chunked" }, input.Http1Connection)); Assert.Equal(StatusCodes.Status400BadRequest, ex.StatusCode); @@ -553,7 +563,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests using (var input = new TestInput()) { input.Http1Connection.Method = method; +#pragma warning disable CS0618 // Type or member is obsolete var ex = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete Http1MessageBody.For(HttpVersion.Http11, new HttpRequestHeaders(), input.Http1Connection)); Assert.Equal(StatusCodes.Status411LengthRequired, ex.StatusCode); @@ -570,7 +582,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests using (var input = new TestInput()) { input.Http1Connection.Method = method; +#pragma warning disable CS0618 // Type or member is obsolete var ex = Assert.Throws(() => +#pragma warning restore CS0618 // Type or member is obsolete Http1MessageBody.For(HttpVersion.Http10, new HttpRequestHeaders(), input.Http1Connection)); Assert.Equal(StatusCodes.Status400BadRequest, ex.StatusCode); @@ -733,7 +747,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests // Time out on the next read input.Http1Connection.SendTimeoutResponse(); +#pragma warning disable CS0618 // Type or member is obsolete var exception = await Assert.ThrowsAsync(async () => await body.ReadAsync()); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(StatusCodes.Status408RequestTimeout, exception.StatusCode); await body.StopAsync(); @@ -768,7 +784,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests mockLogger.Verify(logger => logger.ConnectionBadRequest( It.IsAny(), +#pragma warning disable CS0618 // Type or member is obsolete It.Is(ex => ex.Reason == RequestRejectionReason.RequestBodyTimeout))); +#pragma warning restore CS0618 // Type or member is obsolete await body.StopAsync(); } @@ -796,7 +814,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests using (var ms = new MemoryStream()) { +#pragma warning disable CS0618 // Type or member is obsolete var exception = await Assert.ThrowsAsync(() => stream.CopyToAsync(ms)); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(StatusCodes.Status408RequestTimeout, exception.StatusCode); } @@ -1206,10 +1226,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Application.Output.Complete(); +#pragma warning disable CS0618 // Type or member is obsolete var ex0 = Assert.Throws(() => reader.TryRead(out var readResult)); var ex1 = Assert.Throws(() => reader.TryRead(out var readResult)); var ex2 = await Assert.ThrowsAsync(() => reader.ReadAsync().AsTask()); var ex3 = await Assert.ThrowsAsync(() => reader.ReadAsync().AsTask()); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(RequestRejectionReason.UnexpectedEndOfRequestContent, ex0.Reason); Assert.Equal(RequestRejectionReason.UnexpectedEndOfRequestContent, ex1.Reason); @@ -1231,10 +1253,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests input.Application.Output.Complete(); +#pragma warning disable CS0618 // Type or member is obsolete var ex0 = Assert.Throws(() => reader.TryRead(out var readResult)); var ex1 = Assert.Throws(() => reader.TryRead(out var readResult)); var ex2 = await Assert.ThrowsAsync(() => reader.ReadAsync().AsTask()); var ex3 = await Assert.ThrowsAsync(() => reader.ReadAsync().AsTask()); +#pragma warning restore CS0618 // Type or member is obsolete Assert.Equal(RequestRejectionReason.UnexpectedEndOfRequestContent, ex0.Reason); Assert.Equal(RequestRejectionReason.UnexpectedEndOfRequestContent, ex1.Reason); diff --git a/src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/MockTrace.cs b/src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/MockTrace.cs index bd93636c83..76a5c9443d 100644 --- a/src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/MockTrace.cs +++ b/src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/MockTrace.cs @@ -4,7 +4,6 @@ using System; using System.Net.Http.HPack; using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.Extensions.Logging; @@ -16,7 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance public void ApplicationError(string connectionId, string requestId, Exception ex) { } public IDisposable BeginScope(TState state) => null; public void ConnectionAccepted(string connectionId) { } - public void ConnectionBadRequest(string connectionId, BadHttpRequestException ex) { } + public void ConnectionBadRequest(string connectionId, Microsoft.AspNetCore.Http.BadHttpRequestException ex) { } public void ConnectionDisconnect(string connectionId) { } public void ConnectionError(string connectionId, Exception ex) { } public void ConnectionHeadResponseBodyWrite(string connectionId, long count) { } diff --git a/src/Servers/Kestrel/samples/SampleApp/Startup.cs b/src/Servers/Kestrel/samples/SampleApp/Startup.cs index 6467f4468f..1e90bc1a52 100644 --- a/src/Servers/Kestrel/samples/SampleApp/Startup.cs +++ b/src/Servers/Kestrel/samples/SampleApp/Startup.cs @@ -36,7 +36,7 @@ namespace SampleApp { await next.Invoke(); } - catch (BadHttpRequestException ex) when (ex.StatusCode == StatusCodes.Status413RequestEntityTooLarge) { } + catch (Microsoft.AspNetCore.Http.BadHttpRequestException ex) when (ex.StatusCode == StatusCodes.Status413RequestEntityTooLarge) { } }); app.Run(async context => diff --git a/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs b/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs index 85a7643202..363da59c9d 100644 --- a/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs +++ b/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Testing _trace2.NotAllConnectionsClosedGracefully(); } - public void ConnectionBadRequest(string connectionId, BadHttpRequestException ex) + public void ConnectionBadRequest(string connectionId, Microsoft.AspNetCore.Http.BadHttpRequestException ex) { _trace1.ConnectionBadRequest(connectionId, ex); _trace2.ConnectionBadRequest(connectionId, ex); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/BadHttpRequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/BadHttpRequestTests.cs index c45f773dee..f6cbc2f0a9 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/BadHttpRequestTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/BadHttpRequestTests.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Moq; using Xunit; +using BadHttpRequestException = Microsoft.AspNetCore.Http.BadHttpRequestException; namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { @@ -191,6 +192,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests private async Task TestBadRequest(string request, string expectedResponseStatusCode, string expectedExceptionMessage, string expectedAllowHeader = null) { BadHttpRequestException loggedException = null; + var mockKestrelTrace = new Mock(); mockKestrelTrace .Setup(trace => trace.IsEnabled(LogLevel.Information)) diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs index 72d7c2cc7c..d5b5eb3f21 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Xunit; +using BadHttpRequestException = Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException; namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { @@ -842,7 +843,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { var testContext = new TestServiceContext(LoggerFactory); var readStartedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); +#pragma warning disable CS0618 // Type or member is obsolete var exTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async httpContext => { @@ -853,7 +856,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { await readTask; } +#pragma warning disable CS0618 // Type or member is obsolete catch (BadHttpRequestException badRequestEx) +#pragma warning restore CS0618 // Type or member is obsolete { exTcs.TrySetResult(badRequestEx); } diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2StreamTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2StreamTests.cs index efed04f302..4e0dd12137 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2StreamTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2StreamTests.cs @@ -1569,7 +1569,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests [Fact] public async Task MaxRequestBodySize_ContentLengthOver_413() { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException exception = null; +#pragma warning restore CS0618 // Type or member is obsolete _serviceContext.ServerOptions.Limits.MaxRequestBodySize = 10; var headers = new[] { @@ -1580,7 +1582,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests }; await InitializeConnectionAsync(async context => { +#pragma warning disable CS0618 // Type or member is obsolete exception = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete { var buffer = new byte[100]; while (await context.Request.Body.ReadAsync(buffer, 0, buffer.Length) > 0) { } @@ -1651,7 +1655,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests [Fact] public async Task MaxRequestBodySize_NoContentLength_Over_413() { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException exception = null; +#pragma warning restore CS0618 // Type or member is obsolete _serviceContext.ServerOptions.Limits.MaxRequestBodySize = 10; var headers = new[] { @@ -1661,7 +1667,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests }; await InitializeConnectionAsync(async context => { +#pragma warning disable CS0618 // Type or member is obsolete exception = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete { var buffer = new byte[100]; while (await context.Request.Body.ReadAsync(buffer, 0, buffer.Length) > 0) { } @@ -1699,7 +1707,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests [InlineData(false)] public async Task MaxRequestBodySize_AppCanLowerLimit(bool includeContentLength) { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException exception = null; +#pragma warning restore CS0618 // Type or member is obsolete _serviceContext.ServerOptions.Limits.MaxRequestBodySize = 20; var headers = new[] { @@ -1718,7 +1728,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests { Assert.False(context.Features.Get().IsReadOnly); context.Features.Get().MaxRequestBodySize = 17; +#pragma warning disable CS0618 // Type or member is obsolete exception = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete { var buffer = new byte[100]; while (await context.Request.Body.ReadAsync(buffer, 0, buffer.Length) > 0) { } diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs index 4432e85dc6..de256d5304 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs @@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests _mockTimeoutHandler.Verify(h => h.OnTimeout(TimeoutReason.RequestHeaders), Times.Once); - await WaitForConnectionErrorAsync( + await WaitForConnectionErrorAsync( ignoreNonGoAwayFrames: false, expectedLastStreamId: int.MaxValue, Http2ErrorCode.INTERNAL_ERROR, diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/MaxRequestBodySizeTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/MaxRequestBodySizeTests.cs index ef5e141063..4e75c713e6 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/MaxRequestBodySizeTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/MaxRequestBodySizeTests.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging.Testing; using Xunit; +using BadHttpRequestException = Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException; namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { @@ -22,12 +23,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { // 4 GiB var globalMaxRequestBodySize = 0x100000000; +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { var buffer = new byte[1]; +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx = await Assert.ThrowsAsync( +#pragma warning restore CS0618 // Type or member is obsolete async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); throw requestRejectedEx; }, @@ -62,7 +67,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests var globalMaxRequestBodySize = 0x200000000; // 4 GiB var perRequestMaxRequestBodySize = 0x100000000; +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { @@ -73,7 +80,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests feature.MaxRequestBodySize = perRequestMaxRequestBodySize; var buffer = new byte[1]; +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx = await Assert.ThrowsAsync( +#pragma warning restore CS0618 // Type or member is obsolete async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); throw requestRejectedEx; }, @@ -258,16 +267,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [Fact] public async Task EveryReadFailsWhenContentLengthHeaderExceedsGlobalLimit() { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx1 = null; BadHttpRequestException requestRejectedEx2 = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { var buffer = new byte[1]; +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx1 = await Assert.ThrowsAsync( async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); requestRejectedEx2 = await Assert.ThrowsAsync( async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); +#pragma warning restore CS0618 // Type or member is obsolete throw requestRejectedEx2; }, new TestServiceContext(LoggerFactory) { ServerOptions = { Limits = { MaxRequestBodySize = 0 } } })) @@ -301,12 +314,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { var chunkedPayload = "5;random chunk extension\r\nHello\r\n6\r\n World\r\n0\r\n\r\n"; var globalMaxRequestBodySize = chunkedPayload.Length - 1; +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { var buffer = new byte[11]; +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete { var count = 0; do @@ -389,7 +406,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests var chunkedPayload = "5;random chunk extension\r\nHello\r\n6\r\n World\r\n0\r\n\r\n"; var globalMaxRequestBodySize = chunkedPayload.Length - 1; var firstRequest = true; +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { @@ -411,7 +430,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } else { +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx = await Assert.ThrowsAsync(async () => +#pragma warning restore CS0618 // Type or member is obsolete { do { @@ -457,16 +478,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [Fact] public async Task EveryReadFailsWhenChunkedPayloadExceedsGlobalLimit() { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException requestRejectedEx1 = null; BadHttpRequestException requestRejectedEx2 = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async context => { var buffer = new byte[1]; +#pragma warning disable CS0618 // Type or member is obsolete requestRejectedEx1 = await Assert.ThrowsAsync( async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); requestRejectedEx2 = await Assert.ThrowsAsync( async () => await context.Request.Body.ReadAsync(buffer, 0, 1)); +#pragma warning restore CS0618 // Type or member is obsolete throw requestRejectedEx2; }, new TestServiceContext(LoggerFactory) { ServerOptions = { Limits = { MaxRequestBodySize = 0 } } })) diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestBodyTimeoutTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestBodyTimeoutTests.cs index f96848bc47..93a0c7ff56 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestBodyTimeoutTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestBodyTimeoutTests.cs @@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { await readTask; } - catch (BadHttpRequestException ex) when (ex.StatusCode == 408) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException ex) when (ex.StatusCode == 408) { exceptionSwallowedTcs.SetResult(null); } diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ResponseTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ResponseTests.cs index 0dca63fe5f..4dd609f85b 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ResponseTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ResponseTests.cs @@ -24,6 +24,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; using Moq; using Xunit; +using BadHttpRequestException = Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException; namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { @@ -288,7 +289,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { await context.Request.Body.ReadAsync(new byte[1], 0, 1); } - catch (BadHttpRequestException) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException) { } }, @@ -403,11 +404,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [Fact] public async Task NoErrorResponseSentWhenAppSwallowsBadRequestException() { +#pragma warning disable CS0618 // Type or member is obsolete BadHttpRequestException readException = null; +#pragma warning restore CS0618 // Type or member is obsolete await using (var server = new TestServer(async httpContext => { +#pragma warning disable CS0618 // Type or member is obsolete readException = await Assert.ThrowsAsync( +#pragma warning restore CS0618 // Type or member is obsolete async () => await httpContext.Request.Body.ReadAsync(new byte[1], 0, 1)); }, new TestServiceContext(LoggerFactory))) { @@ -430,8 +435,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests Assert.NotNull(readException); +#pragma warning disable CS0618 // Type or member is obsolete Assert.Contains(TestSink.Writes, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException && ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest); +#pragma warning restore CS0618 // Type or member is obsolete } [Fact] @@ -1265,7 +1272,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { await httpContext.Request.Body.ReadAsync(new byte[1], 0, 1); } - catch (BadHttpRequestException ex) + catch (Microsoft.AspNetCore.Http.BadHttpRequestException ex) { expectedResponse = ex.Message; httpContext.Response.StatusCode = StatusCodes.Status400BadRequest; @@ -1749,8 +1756,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } } +#pragma warning disable CS0618 // Type or member is obsolete Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException && ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest); +#pragma warning restore CS0618 // Type or member is obsolete } [Fact] @@ -1801,8 +1810,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests { while (TestApplicationErrorLogger.Messages.TryDequeue(out var message)) { +#pragma warning disable CS0618 // Type or member is obsolete if (message.EventId.Id == 17 && message.LogLevel <= LogLevel.Debug && message.Exception is BadHttpRequestException && ((BadHttpRequestException)message.Exception).StatusCode == StatusCodes.Status400BadRequest) +#pragma warning restore CS0618 // Type or member is obsolete { foundMessage = true; break; @@ -1862,8 +1873,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } } +#pragma warning disable CS0618 // Type or member is obsolete Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException && ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest); +#pragma warning restore CS0618 // Type or member is obsolete } [Fact] @@ -4117,8 +4130,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests if (sendMalformedRequest) { +#pragma warning disable CS0618 // Type or member is obsolete Assert.Contains(testSink.Writes, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException && ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest); +#pragma warning restore CS0618 // Type or member is obsolete } else {