Skip to content

Instantly share code, notes, and snippets.

@MihaZupan
Created February 22, 2021 08:25
Show Gist options
  • Save MihaZupan/81ecaf69acd23a69d06e5eba228a2fb0 to your computer and use it in GitHub Desktop.
Save MihaZupan/81ecaf69acd23a69d06e5eba228a2fb0 to your computer and use it in GitHub Desktop.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
namespace ReasonPhrasesBenchmarks
{
class Program
{
static void Main() => BenchmarkRunner.Run<Benchmarks>();
}
public class Benchmarks
{
public const int StatusCode = 404;
[Params(null, "Not Found", "Something custom")]
public string ReasonPhrase;
[Benchmark]
public byte[] New() => ReasonPhrases.ToStatusBytes(StatusCode, ReasonPhrase);
[Benchmark]
public byte[] Old() => ReasonPhrases.ToStatusBytesOld(StatusCode, ReasonPhrase);
}
public static class StatusCodes
{
/// <summary>
/// HTTP status code 100.
/// </summary>
public const int Status100Continue = 100;
/// <summary>
/// HTTP status code 101.
/// </summary>
public const int Status101SwitchingProtocols = 101;
/// <summary>
/// HTTP status code 102.
/// </summary>
public const int Status102Processing = 102;
/// <summary>
/// HTTP status code 200.
/// </summary>
public const int Status200OK = 200;
/// <summary>
/// HTTP status code 201.
/// </summary>
public const int Status201Created = 201;
/// <summary>
/// HTTP status code 202.
/// </summary>
public const int Status202Accepted = 202;
/// <summary>
/// HTTP status code 203.
/// </summary>
public const int Status203NonAuthoritative = 203;
/// <summary>
/// HTTP status code 204.
/// </summary>
public const int Status204NoContent = 204;
/// <summary>
/// HTTP status code 205.
/// </summary>
public const int Status205ResetContent = 205;
/// <summary>
/// HTTP status code 206.
/// </summary>
public const int Status206PartialContent = 206;
/// <summary>
/// HTTP status code 207.
/// </summary>
public const int Status207MultiStatus = 207;
/// <summary>
/// HTTP status code 208.
/// </summary>
public const int Status208AlreadyReported = 208;
/// <summary>
/// HTTP status code 226.
/// </summary>
public const int Status226IMUsed = 226;
/// <summary>
/// HTTP status code 300.
/// </summary>
public const int Status300MultipleChoices = 300;
/// <summary>
/// HTTP status code 301.
/// </summary>
public const int Status301MovedPermanently = 301;
/// <summary>
/// HTTP status code 302.
/// </summary>
public const int Status302Found = 302;
/// <summary>
/// HTTP status code 303.
/// </summary>
public const int Status303SeeOther = 303;
/// <summary>
/// HTTP status code 304.
/// </summary>
public const int Status304NotModified = 304;
/// <summary>
/// HTTP status code 305.
/// </summary>
public const int Status305UseProxy = 305;
/// <summary>
/// HTTP status code 306.
/// </summary>
public const int Status306SwitchProxy = 306; // RFC 2616, removed
/// <summary>
/// HTTP status code 307.
/// </summary>
public const int Status307TemporaryRedirect = 307;
/// <summary>
/// HTTP status code 308.
/// </summary>
public const int Status308PermanentRedirect = 308;
/// <summary>
/// HTTP status code 400.
/// </summary>
public const int Status400BadRequest = 400;
/// <summary>
/// HTTP status code 401.
/// </summary>
public const int Status401Unauthorized = 401;
/// <summary>
/// HTTP status code 402.
/// </summary>
public const int Status402PaymentRequired = 402;
/// <summary>
/// HTTP status code 403.
/// </summary>
public const int Status403Forbidden = 403;
/// <summary>
/// HTTP status code 404.
/// </summary>
public const int Status404NotFound = 404;
/// <summary>
/// HTTP status code 405.
/// </summary>
public const int Status405MethodNotAllowed = 405;
/// <summary>
/// HTTP status code 406.
/// </summary>
public const int Status406NotAcceptable = 406;
/// <summary>
/// HTTP status code 407.
/// </summary>
public const int Status407ProxyAuthenticationRequired = 407;
/// <summary>
/// HTTP status code 408.
/// </summary>
public const int Status408RequestTimeout = 408;
/// <summary>
/// HTTP status code 409.
/// </summary>
public const int Status409Conflict = 409;
/// <summary>
/// HTTP status code 410.
/// </summary>
public const int Status410Gone = 410;
/// <summary>
/// HTTP status code 411.
/// </summary>
public const int Status411LengthRequired = 411;
/// <summary>
/// HTTP status code 412.
/// </summary>
public const int Status412PreconditionFailed = 412;
/// <summary>
/// HTTP status code 413.
/// </summary>
public const int Status413RequestEntityTooLarge = 413; // RFC 2616, renamed
/// <summary>
/// HTTP status code 413.
/// </summary>
public const int Status413PayloadTooLarge = 413; // RFC 7231
/// <summary>
/// HTTP status code 414.
/// </summary>
public const int Status414RequestUriTooLong = 414; // RFC 2616, renamed
/// <summary>
/// HTTP status code 414.
/// </summary>
public const int Status414UriTooLong = 414; // RFC 7231
/// <summary>
/// HTTP status code 415.
/// </summary>
public const int Status415UnsupportedMediaType = 415;
/// <summary>
/// HTTP status code 416.
/// </summary>
public const int Status416RequestedRangeNotSatisfiable = 416; // RFC 2616, renamed
/// <summary>
/// HTTP status code 416.
/// </summary>
public const int Status416RangeNotSatisfiable = 416; // RFC 7233
/// <summary>
/// HTTP status code 417.
/// </summary>
public const int Status417ExpectationFailed = 417;
/// <summary>
/// HTTP status code 418.
/// </summary>
public const int Status418ImATeapot = 418;
/// <summary>
/// HTTP status code 419.
/// </summary>
public const int Status419AuthenticationTimeout = 419; // Not defined in any RFC
/// <summary>
/// HTTP status code 422.
/// </summary>
public const int Status421MisdirectedRequest = 421;
/// <summary>
/// HTTP status code 422.
/// </summary>
public const int Status422UnprocessableEntity = 422;
/// <summary>
/// HTTP status code 423.
/// </summary>
public const int Status423Locked = 423;
/// <summary>
/// HTTP status code 424.
/// </summary>
public const int Status424FailedDependency = 424;
/// <summary>
/// HTTP status code 426.
/// </summary>
public const int Status426UpgradeRequired = 426;
/// <summary>
/// HTTP status code 428.
/// </summary>
public const int Status428PreconditionRequired = 428;
/// <summary>
/// HTTP status code 429.
/// </summary>
public const int Status429TooManyRequests = 429;
/// <summary>
/// HTTP status code 431.
/// </summary>
public const int Status431RequestHeaderFieldsTooLarge = 431;
/// <summary>
/// HTTP status code 451.
/// </summary>
public const int Status451UnavailableForLegalReasons = 451;
/// <summary>
/// HTTP status code 500.
/// </summary>
public const int Status500InternalServerError = 500;
/// <summary>
/// HTTP status code 501.
/// </summary>
public const int Status501NotImplemented = 501;
/// <summary>
/// HTTP status code 502.
/// </summary>
public const int Status502BadGateway = 502;
/// <summary>
/// HTTP status code 503.
/// </summary>
public const int Status503ServiceUnavailable = 503;
/// <summary>
/// HTTP status code 504.
/// </summary>
public const int Status504GatewayTimeout = 504;
/// <summary>
/// HTTP status code 505.
/// </summary>
public const int Status505HttpVersionNotsupported = 505;
/// <summary>
/// HTTP status code 506.
/// </summary>
public const int Status506VariantAlsoNegotiates = 506;
/// <summary>
/// HTTP status code 507.
/// </summary>
public const int Status507InsufficientStorage = 507;
/// <summary>
/// HTTP status code 508.
/// </summary>
public const int Status508LoopDetected = 508;
/// <summary>
/// HTTP status code 510.
/// </summary>
public const int Status510NotExtended = 510;
/// <summary>
/// HTTP status code 511.
/// </summary>
public const int Status511NetworkAuthenticationRequired = 511;
}
internal static class ReasonPhrases
{
private static readonly byte[] _bytesStatus100 = CreateStatusBytes(StatusCodes.Status100Continue);
private static readonly byte[] _bytesStatus101 = CreateStatusBytes(StatusCodes.Status101SwitchingProtocols);
private static readonly byte[] _bytesStatus102 = CreateStatusBytes(StatusCodes.Status102Processing);
private static readonly byte[] _bytesStatus200 = CreateStatusBytes(StatusCodes.Status200OK);
private static readonly byte[] _bytesStatus201 = CreateStatusBytes(StatusCodes.Status201Created);
private static readonly byte[] _bytesStatus202 = CreateStatusBytes(StatusCodes.Status202Accepted);
private static readonly byte[] _bytesStatus203 = CreateStatusBytes(StatusCodes.Status203NonAuthoritative);
private static readonly byte[] _bytesStatus204 = CreateStatusBytes(StatusCodes.Status204NoContent);
private static readonly byte[] _bytesStatus205 = CreateStatusBytes(StatusCodes.Status205ResetContent);
private static readonly byte[] _bytesStatus206 = CreateStatusBytes(StatusCodes.Status206PartialContent);
private static readonly byte[] _bytesStatus207 = CreateStatusBytes(StatusCodes.Status207MultiStatus);
private static readonly byte[] _bytesStatus208 = CreateStatusBytes(StatusCodes.Status208AlreadyReported);
private static readonly byte[] _bytesStatus226 = CreateStatusBytes(StatusCodes.Status226IMUsed);
private static readonly byte[] _bytesStatus300 = CreateStatusBytes(StatusCodes.Status300MultipleChoices);
private static readonly byte[] _bytesStatus301 = CreateStatusBytes(StatusCodes.Status301MovedPermanently);
private static readonly byte[] _bytesStatus302 = CreateStatusBytes(StatusCodes.Status302Found);
private static readonly byte[] _bytesStatus303 = CreateStatusBytes(StatusCodes.Status303SeeOther);
private static readonly byte[] _bytesStatus304 = CreateStatusBytes(StatusCodes.Status304NotModified);
private static readonly byte[] _bytesStatus305 = CreateStatusBytes(StatusCodes.Status305UseProxy);
private static readonly byte[] _bytesStatus306 = CreateStatusBytes(StatusCodes.Status306SwitchProxy);
private static readonly byte[] _bytesStatus307 = CreateStatusBytes(StatusCodes.Status307TemporaryRedirect);
private static readonly byte[] _bytesStatus308 = CreateStatusBytes(StatusCodes.Status308PermanentRedirect);
private static readonly byte[] _bytesStatus400 = CreateStatusBytes(StatusCodes.Status400BadRequest);
private static readonly byte[] _bytesStatus401 = CreateStatusBytes(StatusCodes.Status401Unauthorized);
private static readonly byte[] _bytesStatus402 = CreateStatusBytes(StatusCodes.Status402PaymentRequired);
private static readonly byte[] _bytesStatus403 = CreateStatusBytes(StatusCodes.Status403Forbidden);
private static readonly byte[] _bytesStatus404 = CreateStatusBytes(StatusCodes.Status404NotFound);
private static readonly byte[] _bytesStatus405 = CreateStatusBytes(StatusCodes.Status405MethodNotAllowed);
private static readonly byte[] _bytesStatus406 = CreateStatusBytes(StatusCodes.Status406NotAcceptable);
private static readonly byte[] _bytesStatus407 = CreateStatusBytes(StatusCodes.Status407ProxyAuthenticationRequired);
private static readonly byte[] _bytesStatus408 = CreateStatusBytes(StatusCodes.Status408RequestTimeout);
private static readonly byte[] _bytesStatus409 = CreateStatusBytes(StatusCodes.Status409Conflict);
private static readonly byte[] _bytesStatus410 = CreateStatusBytes(StatusCodes.Status410Gone);
private static readonly byte[] _bytesStatus411 = CreateStatusBytes(StatusCodes.Status411LengthRequired);
private static readonly byte[] _bytesStatus412 = CreateStatusBytes(StatusCodes.Status412PreconditionFailed);
private static readonly byte[] _bytesStatus413 = CreateStatusBytes(StatusCodes.Status413PayloadTooLarge);
private static readonly byte[] _bytesStatus414 = CreateStatusBytes(StatusCodes.Status414UriTooLong);
private static readonly byte[] _bytesStatus415 = CreateStatusBytes(StatusCodes.Status415UnsupportedMediaType);
private static readonly byte[] _bytesStatus416 = CreateStatusBytes(StatusCodes.Status416RangeNotSatisfiable);
private static readonly byte[] _bytesStatus417 = CreateStatusBytes(StatusCodes.Status417ExpectationFailed);
private static readonly byte[] _bytesStatus418 = CreateStatusBytes(StatusCodes.Status418ImATeapot);
private static readonly byte[] _bytesStatus419 = CreateStatusBytes(StatusCodes.Status419AuthenticationTimeout);
private static readonly byte[] _bytesStatus421 = CreateStatusBytes(StatusCodes.Status421MisdirectedRequest);
private static readonly byte[] _bytesStatus422 = CreateStatusBytes(StatusCodes.Status422UnprocessableEntity);
private static readonly byte[] _bytesStatus423 = CreateStatusBytes(StatusCodes.Status423Locked);
private static readonly byte[] _bytesStatus424 = CreateStatusBytes(StatusCodes.Status424FailedDependency);
private static readonly byte[] _bytesStatus426 = CreateStatusBytes(StatusCodes.Status426UpgradeRequired);
private static readonly byte[] _bytesStatus428 = CreateStatusBytes(StatusCodes.Status428PreconditionRequired);
private static readonly byte[] _bytesStatus429 = CreateStatusBytes(StatusCodes.Status429TooManyRequests);
private static readonly byte[] _bytesStatus431 = CreateStatusBytes(StatusCodes.Status431RequestHeaderFieldsTooLarge);
private static readonly byte[] _bytesStatus451 = CreateStatusBytes(StatusCodes.Status451UnavailableForLegalReasons);
private static readonly byte[] _bytesStatus500 = CreateStatusBytes(StatusCodes.Status500InternalServerError);
private static readonly byte[] _bytesStatus501 = CreateStatusBytes(StatusCodes.Status501NotImplemented);
private static readonly byte[] _bytesStatus502 = CreateStatusBytes(StatusCodes.Status502BadGateway);
private static readonly byte[] _bytesStatus503 = CreateStatusBytes(StatusCodes.Status503ServiceUnavailable);
private static readonly byte[] _bytesStatus504 = CreateStatusBytes(StatusCodes.Status504GatewayTimeout);
private static readonly byte[] _bytesStatus505 = CreateStatusBytes(StatusCodes.Status505HttpVersionNotsupported);
private static readonly byte[] _bytesStatus506 = CreateStatusBytes(StatusCodes.Status506VariantAlsoNegotiates);
private static readonly byte[] _bytesStatus507 = CreateStatusBytes(StatusCodes.Status507InsufficientStorage);
private static readonly byte[] _bytesStatus508 = CreateStatusBytes(StatusCodes.Status508LoopDetected);
private static readonly byte[] _bytesStatus510 = CreateStatusBytes(StatusCodes.Status510NotExtended);
private static readonly byte[] _bytesStatus511 = CreateStatusBytes(StatusCodes.Status511NetworkAuthenticationRequired);
private static byte[] CreateStatusBytes(int statusCode)
{
var reasonPhrase = WebUtilitiesReasonPhrases.GetReasonPhrase(statusCode);
Debug.Assert(!string.IsNullOrEmpty(reasonPhrase));
return CreateStatusBytes(statusCode, reasonPhrase);
}
private static byte[] CreateStatusBytes(int statusCode, string? reasonPhrase)
{
// https://tools.ietf.org/html/rfc7230#section-3.1.2 requires trailing whitespace regardless of reason phrase
return Encoding.ASCII.GetBytes(statusCode.ToString(CultureInfo.InvariantCulture) + " " + reasonPhrase);
}
public static byte[] ToStatusBytes(int statusCode, string? reasonPhrase = null)
{
var candidate = statusCode switch
{
StatusCodes.Status100Continue => _bytesStatus100,
StatusCodes.Status101SwitchingProtocols => _bytesStatus101,
StatusCodes.Status102Processing => _bytesStatus102,
StatusCodes.Status200OK => _bytesStatus200,
StatusCodes.Status201Created => _bytesStatus201,
StatusCodes.Status202Accepted => _bytesStatus202,
StatusCodes.Status203NonAuthoritative => _bytesStatus203,
StatusCodes.Status204NoContent => _bytesStatus204,
StatusCodes.Status205ResetContent => _bytesStatus205,
StatusCodes.Status206PartialContent => _bytesStatus206,
StatusCodes.Status207MultiStatus => _bytesStatus207,
StatusCodes.Status208AlreadyReported => _bytesStatus208,
StatusCodes.Status226IMUsed => _bytesStatus226,
StatusCodes.Status300MultipleChoices => _bytesStatus300,
StatusCodes.Status301MovedPermanently => _bytesStatus301,
StatusCodes.Status302Found => _bytesStatus302,
StatusCodes.Status303SeeOther => _bytesStatus303,
StatusCodes.Status304NotModified => _bytesStatus304,
StatusCodes.Status305UseProxy => _bytesStatus305,
StatusCodes.Status306SwitchProxy => _bytesStatus306,
StatusCodes.Status307TemporaryRedirect => _bytesStatus307,
StatusCodes.Status308PermanentRedirect => _bytesStatus308,
StatusCodes.Status400BadRequest => _bytesStatus400,
StatusCodes.Status401Unauthorized => _bytesStatus401,
StatusCodes.Status402PaymentRequired => _bytesStatus402,
StatusCodes.Status403Forbidden => _bytesStatus403,
StatusCodes.Status404NotFound => _bytesStatus404,
StatusCodes.Status405MethodNotAllowed => _bytesStatus405,
StatusCodes.Status406NotAcceptable => _bytesStatus406,
StatusCodes.Status407ProxyAuthenticationRequired => _bytesStatus407,
StatusCodes.Status408RequestTimeout => _bytesStatus408,
StatusCodes.Status409Conflict => _bytesStatus409,
StatusCodes.Status410Gone => _bytesStatus410,
StatusCodes.Status411LengthRequired => _bytesStatus411,
StatusCodes.Status412PreconditionFailed => _bytesStatus412,
StatusCodes.Status413PayloadTooLarge => _bytesStatus413,
StatusCodes.Status414UriTooLong => _bytesStatus414,
StatusCodes.Status415UnsupportedMediaType => _bytesStatus415,
StatusCodes.Status416RangeNotSatisfiable => _bytesStatus416,
StatusCodes.Status417ExpectationFailed => _bytesStatus417,
StatusCodes.Status418ImATeapot => _bytesStatus418,
StatusCodes.Status419AuthenticationTimeout => _bytesStatus419,
StatusCodes.Status421MisdirectedRequest => _bytesStatus421,
StatusCodes.Status422UnprocessableEntity => _bytesStatus422,
StatusCodes.Status423Locked => _bytesStatus423,
StatusCodes.Status424FailedDependency => _bytesStatus424,
StatusCodes.Status426UpgradeRequired => _bytesStatus426,
StatusCodes.Status428PreconditionRequired => _bytesStatus428,
StatusCodes.Status429TooManyRequests => _bytesStatus429,
StatusCodes.Status431RequestHeaderFieldsTooLarge => _bytesStatus431,
StatusCodes.Status451UnavailableForLegalReasons => _bytesStatus451,
StatusCodes.Status500InternalServerError => _bytesStatus500,
StatusCodes.Status501NotImplemented => _bytesStatus501,
StatusCodes.Status502BadGateway => _bytesStatus502,
StatusCodes.Status503ServiceUnavailable => _bytesStatus503,
StatusCodes.Status504GatewayTimeout => _bytesStatus504,
StatusCodes.Status505HttpVersionNotsupported => _bytesStatus505,
StatusCodes.Status506VariantAlsoNegotiates => _bytesStatus506,
StatusCodes.Status507InsufficientStorage => _bytesStatus507,
StatusCodes.Status508LoopDetected => _bytesStatus508,
StatusCodes.Status510NotExtended => _bytesStatus510,
StatusCodes.Status511NetworkAuthenticationRequired => _bytesStatus511,
_ => null
};
if (candidate is not null && (string.IsNullOrEmpty(reasonPhrase) || WebUtilitiesReasonPhrases.GetReasonPhrase(statusCode) == reasonPhrase))
{
return candidate;
}
return CreateStatusBytes(statusCode, reasonPhrase);
}
public static byte[] ToStatusBytesOld(int statusCode, string? reasonPhrase = null)
{
if (string.IsNullOrEmpty(reasonPhrase))
{
switch (statusCode)
{
case StatusCodes.Status100Continue:
return _bytesStatus100;
case StatusCodes.Status101SwitchingProtocols:
return _bytesStatus101;
case StatusCodes.Status102Processing:
return _bytesStatus102;
case StatusCodes.Status200OK:
return _bytesStatus200;
case StatusCodes.Status201Created:
return _bytesStatus201;
case StatusCodes.Status202Accepted:
return _bytesStatus202;
case StatusCodes.Status203NonAuthoritative:
return _bytesStatus203;
case StatusCodes.Status204NoContent:
return _bytesStatus204;
case StatusCodes.Status205ResetContent:
return _bytesStatus205;
case StatusCodes.Status206PartialContent:
return _bytesStatus206;
case StatusCodes.Status207MultiStatus:
return _bytesStatus207;
case StatusCodes.Status208AlreadyReported:
return _bytesStatus208;
case StatusCodes.Status226IMUsed:
return _bytesStatus226;
case StatusCodes.Status300MultipleChoices:
return _bytesStatus300;
case StatusCodes.Status301MovedPermanently:
return _bytesStatus301;
case StatusCodes.Status302Found:
return _bytesStatus302;
case StatusCodes.Status303SeeOther:
return _bytesStatus303;
case StatusCodes.Status304NotModified:
return _bytesStatus304;
case StatusCodes.Status305UseProxy:
return _bytesStatus305;
case StatusCodes.Status306SwitchProxy:
return _bytesStatus306;
case StatusCodes.Status307TemporaryRedirect:
return _bytesStatus307;
case StatusCodes.Status308PermanentRedirect:
return _bytesStatus308;
case StatusCodes.Status400BadRequest:
return _bytesStatus400;
case StatusCodes.Status401Unauthorized:
return _bytesStatus401;
case StatusCodes.Status402PaymentRequired:
return _bytesStatus402;
case StatusCodes.Status403Forbidden:
return _bytesStatus403;
case StatusCodes.Status404NotFound:
return _bytesStatus404;
case StatusCodes.Status405MethodNotAllowed:
return _bytesStatus405;
case StatusCodes.Status406NotAcceptable:
return _bytesStatus406;
case StatusCodes.Status407ProxyAuthenticationRequired:
return _bytesStatus407;
case StatusCodes.Status408RequestTimeout:
return _bytesStatus408;
case StatusCodes.Status409Conflict:
return _bytesStatus409;
case StatusCodes.Status410Gone:
return _bytesStatus410;
case StatusCodes.Status411LengthRequired:
return _bytesStatus411;
case StatusCodes.Status412PreconditionFailed:
return _bytesStatus412;
case StatusCodes.Status413PayloadTooLarge:
return _bytesStatus413;
case StatusCodes.Status414UriTooLong:
return _bytesStatus414;
case StatusCodes.Status415UnsupportedMediaType:
return _bytesStatus415;
case StatusCodes.Status416RangeNotSatisfiable:
return _bytesStatus416;
case StatusCodes.Status417ExpectationFailed:
return _bytesStatus417;
case StatusCodes.Status418ImATeapot:
return _bytesStatus418;
case StatusCodes.Status419AuthenticationTimeout:
return _bytesStatus419;
case StatusCodes.Status421MisdirectedRequest:
return _bytesStatus421;
case StatusCodes.Status422UnprocessableEntity:
return _bytesStatus422;
case StatusCodes.Status423Locked:
return _bytesStatus423;
case StatusCodes.Status424FailedDependency:
return _bytesStatus424;
case StatusCodes.Status426UpgradeRequired:
return _bytesStatus426;
case StatusCodes.Status428PreconditionRequired:
return _bytesStatus428;
case StatusCodes.Status429TooManyRequests:
return _bytesStatus429;
case StatusCodes.Status431RequestHeaderFieldsTooLarge:
return _bytesStatus431;
case StatusCodes.Status451UnavailableForLegalReasons:
return _bytesStatus451;
case StatusCodes.Status500InternalServerError:
return _bytesStatus500;
case StatusCodes.Status501NotImplemented:
return _bytesStatus501;
case StatusCodes.Status502BadGateway:
return _bytesStatus502;
case StatusCodes.Status503ServiceUnavailable:
return _bytesStatus503;
case StatusCodes.Status504GatewayTimeout:
return _bytesStatus504;
case StatusCodes.Status505HttpVersionNotsupported:
return _bytesStatus505;
case StatusCodes.Status506VariantAlsoNegotiates:
return _bytesStatus506;
case StatusCodes.Status507InsufficientStorage:
return _bytesStatus507;
case StatusCodes.Status508LoopDetected:
return _bytesStatus508;
case StatusCodes.Status510NotExtended:
return _bytesStatus510;
case StatusCodes.Status511NetworkAuthenticationRequired:
return _bytesStatus511;
default:
var predefinedReasonPhrase = WebUtilitiesReasonPhrases.GetReasonPhrase(statusCode);
// https://tools.ietf.org/html/rfc7230#section-3.1.2 requires trailing whitespace regardless of reason phrase
var formattedStatusCode = statusCode.ToString(CultureInfo.InvariantCulture) + " ";
return string.IsNullOrEmpty(predefinedReasonPhrase)
? Encoding.ASCII.GetBytes(formattedStatusCode)
: Encoding.ASCII.GetBytes(formattedStatusCode + predefinedReasonPhrase);
}
}
return Encoding.ASCII.GetBytes(statusCode.ToString(CultureInfo.InvariantCulture) + " " + reasonPhrase);
}
}
public static class WebUtilitiesReasonPhrases
{
// Status Codes listed at http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
private static readonly Dictionary<int, string> Phrases = new()
{
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 102, "Processing" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 207, "Multi-Status" },
{ 208, "Already Reported" },
{ 226, "IM Used" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 306, "Switch Proxy" },
{ 307, "Temporary Redirect" },
{ 308, "Permanent Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Payload Too Large" },
{ 414, "URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 418, "I'm a teapot" },
{ 419, "Authentication Timeout" },
{ 421, "Misdirected Request" },
{ 422, "Unprocessable Entity" },
{ 423, "Locked" },
{ 424, "Failed Dependency" },
{ 426, "Upgrade Required" },
{ 428, "Precondition Required" },
{ 429, "Too Many Requests" },
{ 431, "Request Header Fields Too Large" },
{ 451, "Unavailable For Legal Reasons" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
{ 506, "Variant Also Negotiates" },
{ 507, "Insufficient Storage" },
{ 508, "Loop Detected" },
{ 510, "Not Extended" },
{ 511, "Network Authentication Required" },
};
/// <summary>
/// Gets the reason phrase for the specified status code.
/// </summary>
/// <param name="statusCode">The status code.</param>
/// <returns>The reason phrase, or <see cref="string.Empty"/> if the status code is unknown.</returns>
public static string GetReasonPhrase(int statusCode)
{
return Phrases.TryGetValue(statusCode, out var phrase) ? phrase : string.Empty;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment