178 lines
10 KiB
C#
178 lines
10 KiB
C#
// 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 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
|
|
{
|
|
private BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason)
|
|
: this(message, statusCode, reason, null)
|
|
{ }
|
|
|
|
private BadHttpRequestException(string message, int statusCode, RequestRejectionReason reason, HttpMethod? requiredMethod)
|
|
: base(message)
|
|
{
|
|
StatusCode = statusCode;
|
|
Reason = reason;
|
|
|
|
if (requiredMethod.HasValue)
|
|
{
|
|
AllowedHeader = HttpUtilities.MethodToString(requiredMethod.Value);
|
|
}
|
|
}
|
|
|
|
internal int StatusCode { get; }
|
|
|
|
internal StringValues AllowedHeader { get; }
|
|
|
|
internal RequestRejectionReason Reason { get; }
|
|
|
|
[StackTraceHidden]
|
|
internal static void Throw(RequestRejectionReason reason)
|
|
{
|
|
throw GetException(reason);
|
|
}
|
|
|
|
[StackTraceHidden]
|
|
#pragma warning disable PUB0001 // Pubternal type in public API
|
|
public static void Throw(RequestRejectionReason reason, HttpMethod method)
|
|
=> throw GetException(reason, method.ToString().ToUpperInvariant());
|
|
#pragma warning restore PUB0001 // Pubternal type in public API
|
|
|
|
[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, in StringValues detail)
|
|
{
|
|
throw GetException(reason, detail.ToString());
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
internal static BadHttpRequestException GetException(RequestRejectionReason reason, string detail)
|
|
{
|
|
BadHttpRequestException ex;
|
|
switch (reason)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
} |