mirror of
https://github.com/matrix-construct/construct
synced 2024-06-11 06:28:55 +02:00
ircd::http: Add status category enum; move static grammars out of function; minor reorg enums.
This commit is contained in:
parent
59665babae
commit
09fe270c54
|
@ -14,7 +14,6 @@
|
|||
/// HyperText TransPort: formal grammars & tools
|
||||
namespace ircd::http
|
||||
{
|
||||
enum code :ushort;
|
||||
struct error;
|
||||
struct line;
|
||||
struct query;
|
||||
|
@ -23,8 +22,14 @@ namespace ircd::http
|
|||
struct request;
|
||||
struct response;
|
||||
|
||||
string_view status(const code &);
|
||||
code status(const string_view &);
|
||||
enum code :ushort;
|
||||
string_view status(const enum code &) noexcept;
|
||||
enum code status(const string_view &);
|
||||
|
||||
enum class category :uint8_t;
|
||||
string_view category(const enum category &) noexcept;
|
||||
enum category category(const enum code &) noexcept;
|
||||
enum category category(const string_view &) noexcept;
|
||||
|
||||
void writeline(window_buffer &);
|
||||
void writeline(window_buffer &, const window_buffer::closure &);
|
||||
|
@ -38,21 +43,95 @@ namespace ircd::http
|
|||
bool has(const vector_view<const header> &, const string_view &key);
|
||||
}
|
||||
|
||||
/// HTTP Status classifications.
|
||||
enum class ircd::http::category
|
||||
:uint8_t
|
||||
{
|
||||
NONE = 0, ///< Sentinel
|
||||
INFO = 1, ///< Informational
|
||||
SUCCESS = 2, ///< Successful
|
||||
REDIRECT = 3, ///< Redirectional
|
||||
ERROR = 4, ///< Erroneous
|
||||
SERVER = 6, ///< Server Error
|
||||
UNKNOWN = 7, /// Pair with default case in switch/tables
|
||||
};
|
||||
|
||||
/// HTTP Status codes.
|
||||
enum ircd::http::code
|
||||
:ushort
|
||||
{
|
||||
CONTINUE = 100,
|
||||
SWITCHING_PROTOCOLS = 101,
|
||||
PROCESSING = 102,
|
||||
EARLY_HINTS = 103,
|
||||
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
ACCEPTED = 202,
|
||||
NON_AUTHORITATIVE_INFORMATION = 203,
|
||||
NO_CONTENT = 204,
|
||||
PARTIAL_CONTENT = 206,
|
||||
|
||||
MULTIPLE_CHOICES = 300,
|
||||
MOVED_PERMANENTLY = 301,
|
||||
FOUND = 302,
|
||||
SEE_OTHER = 303,
|
||||
NOT_MODIFIED = 304,
|
||||
USE_PROXY = 305,
|
||||
SWITCH_PROXY = 306,
|
||||
TEMPORARY_REDIRECT = 307,
|
||||
PERMANENT_REDIRECT = 308,
|
||||
|
||||
BAD_REQUEST = 400,
|
||||
UNAUTHORIZED = 401,
|
||||
FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
METHOD_NOT_ALLOWED = 405,
|
||||
NOT_ACCEPTABLE = 406,
|
||||
REQUEST_TIMEOUT = 408,
|
||||
CONFLICT = 409,
|
||||
GONE = 410,
|
||||
LENGTH_REQUIRED = 411,
|
||||
PAYLOAD_TOO_LARGE = 413,
|
||||
REQUEST_URI_TOO_LONG = 414,
|
||||
UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
RANGE_NOT_SATISFIABLE = 416,
|
||||
EXPECTATION_FAILED = 417,
|
||||
IM_A_TEAPOT = 418,
|
||||
UNPROCESSABLE_ENTITY = 422,
|
||||
PRECONDITION_REQUIRED = 428,
|
||||
TOO_MANY_REQUESTS = 429,
|
||||
REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
|
||||
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
NOT_IMPLEMENTED = 501,
|
||||
BAD_GATEWAY = 502,
|
||||
SERVICE_UNAVAILABLE = 503,
|
||||
GATEWAY_TIMEOUT = 504,
|
||||
HTTP_VERSION_NOT_SUPPORTED = 505,
|
||||
INSUFFICIENT_STORAGE = 507,
|
||||
|
||||
CLOUDFLARE_REFUSED = 521,
|
||||
CLOUDFLARE_TIMEDOUT = 522,
|
||||
CLOUDFLARE_UNREACHABLE = 523,
|
||||
CLOUDFLARE_REQUEST_TIMEOUT = 524,
|
||||
};
|
||||
|
||||
/// Root exception for HTTP.
|
||||
struct ircd::http::error
|
||||
:ircd::error
|
||||
{
|
||||
std::string content;
|
||||
std::string headers;
|
||||
http::code code {http::code(0)};
|
||||
enum code code {http::code(0)};
|
||||
|
||||
explicit operator bool() const { return code != http::code(0); }
|
||||
bool operator!() const { return !bool(*this); }
|
||||
|
||||
error() = default;
|
||||
error(const http::code &, std::string content = {}, std::string headers = {});
|
||||
error(const http::code &, std::string content, const vector_view<const header> &);
|
||||
template<class... args> error(const string_view &fmt, const http::code &, args&&...);
|
||||
error(const enum code &, std::string content = {}, std::string headers = {});
|
||||
error(const enum code &, std::string content, const vector_view<const header> &);
|
||||
template<class... args> error(const string_view &fmt, const enum code &, args&&...);
|
||||
~error() noexcept;
|
||||
};
|
||||
|
||||
|
@ -263,7 +342,7 @@ struct ircd::http::response
|
|||
|
||||
// compose a response into buffer
|
||||
response(window_buffer &,
|
||||
const code &,
|
||||
const enum code &,
|
||||
const size_t &content_length = 0,
|
||||
const string_view &content_type = {},
|
||||
const http::headers &headers = {},
|
||||
|
@ -302,69 +381,6 @@ struct ircd::http::response::chunk
|
|||
chunk() = default;
|
||||
};
|
||||
|
||||
//
|
||||
// Add more as you go...
|
||||
//
|
||||
enum ircd::http::code
|
||||
:ushort
|
||||
{
|
||||
CONTINUE = 100,
|
||||
SWITCHING_PROTOCOLS = 101,
|
||||
PROCESSING = 102,
|
||||
EARLY_HINTS = 103,
|
||||
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
ACCEPTED = 202,
|
||||
NON_AUTHORITATIVE_INFORMATION = 203,
|
||||
NO_CONTENT = 204,
|
||||
PARTIAL_CONTENT = 206,
|
||||
|
||||
MULTIPLE_CHOICES = 300,
|
||||
MOVED_PERMANENTLY = 301,
|
||||
FOUND = 302,
|
||||
SEE_OTHER = 303,
|
||||
NOT_MODIFIED = 304,
|
||||
USE_PROXY = 305,
|
||||
SWITCH_PROXY = 306,
|
||||
TEMPORARY_REDIRECT = 307,
|
||||
PERMANENT_REDIRECT = 308,
|
||||
|
||||
BAD_REQUEST = 400,
|
||||
UNAUTHORIZED = 401,
|
||||
FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
METHOD_NOT_ALLOWED = 405,
|
||||
NOT_ACCEPTABLE = 406,
|
||||
REQUEST_TIMEOUT = 408,
|
||||
CONFLICT = 409,
|
||||
GONE = 410,
|
||||
LENGTH_REQUIRED = 411,
|
||||
PAYLOAD_TOO_LARGE = 413,
|
||||
REQUEST_URI_TOO_LONG = 414,
|
||||
UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
RANGE_NOT_SATISFIABLE = 416,
|
||||
EXPECTATION_FAILED = 417,
|
||||
IM_A_TEAPOT = 418,
|
||||
UNPROCESSABLE_ENTITY = 422,
|
||||
PRECONDITION_REQUIRED = 428,
|
||||
TOO_MANY_REQUESTS = 429,
|
||||
REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
|
||||
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
NOT_IMPLEMENTED = 501,
|
||||
BAD_GATEWAY = 502,
|
||||
SERVICE_UNAVAILABLE = 503,
|
||||
GATEWAY_TIMEOUT = 504,
|
||||
HTTP_VERSION_NOT_SUPPORTED = 505,
|
||||
INSUFFICIENT_STORAGE = 507,
|
||||
|
||||
CLOUDFLARE_REFUSED = 521,
|
||||
CLOUDFLARE_TIMEDOUT = 522,
|
||||
CLOUDFLARE_UNREACHABLE = 523,
|
||||
CLOUDFLARE_REQUEST_TIMEOUT = 524,
|
||||
};
|
||||
|
||||
template<size_t MAX>
|
||||
inline ircd::vector_view<ircd::string_view>
|
||||
ircd::http::query::string::array(const mutable_buffer &buf,
|
||||
|
|
113
ircd/http.cc
113
ircd/http.cc
|
@ -117,7 +117,10 @@ struct ircd::http::grammar
|
|||
:qi::grammar<const char *, unused_type>
|
||||
{
|
||||
using it = const char *;
|
||||
template<class R = unused_type, class... S> using rule = qi::rule<it, R, S...>;
|
||||
|
||||
template<class R = unused_type,
|
||||
class... S>
|
||||
using rule = qi::rule<it, R, S...>;
|
||||
|
||||
rule<> NUL { lit('\0') ,"nul" };
|
||||
|
||||
|
@ -143,7 +146,6 @@ struct ircd::http::grammar
|
|||
rule<string_view> line { *ws >> -string >> CRLF ,"line" };
|
||||
|
||||
rule<string_view> status { raw[repeat(3)[char_("0-9")]] ,"status" };
|
||||
rule<short> status_code { short_ ,"status code" };
|
||||
rule<string_view> reason { string ,"status" };
|
||||
|
||||
rule<string_view> head_key { raw[+(char_ - (illegal | ws | colon))] ,"head key" };
|
||||
|
@ -1241,33 +1243,58 @@ noexcept
|
|||
// status
|
||||
//
|
||||
|
||||
ircd::http::code
|
||||
#pragma GCC visibility push(internal)
|
||||
namespace ircd::http
|
||||
{
|
||||
extern const parser::rule<uint8_t> status_codepoint;
|
||||
extern const parser::rule<enum category> status_category;
|
||||
extern const parser::rule<enum code> status_code;
|
||||
}
|
||||
#pragma GCC visibility pop
|
||||
|
||||
decltype(ircd::http::status_codepoint)
|
||||
ircd::http::status_codepoint
|
||||
{
|
||||
qi::uint_parser<uint8_t, 10, 1, 1>{}
|
||||
,"status codepoint"
|
||||
};
|
||||
|
||||
decltype(ircd::http::status_category)
|
||||
ircd::http::status_category
|
||||
{
|
||||
&char_("1-9") >> status_codepoint >> omit[repeat(2)[char_("0-9")] >> (eoi | parser.ws)]
|
||||
};
|
||||
|
||||
decltype(ircd::http::status_code)
|
||||
ircd::http::status_code
|
||||
{
|
||||
qi::uint_parser<uint16_t, 10, 3, 3>{} >> omit[eoi | parser.ws]
|
||||
,"status code"
|
||||
};
|
||||
|
||||
enum ircd::http::code
|
||||
ircd::http::status(const string_view &str)
|
||||
{
|
||||
static const auto grammar
|
||||
{
|
||||
parser.status_code
|
||||
};
|
||||
|
||||
short ret;
|
||||
const char *start(str.data());
|
||||
const char *start(begin(str)), *const stop(end(str));
|
||||
const bool parsed
|
||||
{
|
||||
parser(start, start + str.size(), grammar, ret)
|
||||
parser(start, stop, status_code, ret)
|
||||
};
|
||||
|
||||
if(!parsed || ret < 0 || ret >= 1000)
|
||||
if(!parsed)
|
||||
throw ircd::error
|
||||
{
|
||||
"Invalid HTTP status code"
|
||||
};
|
||||
|
||||
assert(ret >= 0 && ret < 1000);
|
||||
return http::code(ret);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::http::status(const http::code &code)
|
||||
try
|
||||
ircd::http::status(const enum code &code)
|
||||
noexcept try
|
||||
{
|
||||
return reason.at(code);
|
||||
}
|
||||
|
@ -1280,3 +1307,63 @@ catch(const std::out_of_range &e)
|
|||
|
||||
return ""_sv;
|
||||
}
|
||||
|
||||
enum ircd::http::category
|
||||
ircd::http::category(const string_view &str)
|
||||
noexcept
|
||||
{
|
||||
enum category ret;
|
||||
const char *start(begin(str)), *const stop(end(str));
|
||||
const bool parsed
|
||||
{
|
||||
parser(start, stop, status_category, ret)
|
||||
};
|
||||
|
||||
if(!parsed || ret > category::UNKNOWN)
|
||||
ret = category::UNKNOWN;
|
||||
|
||||
assert(uint8_t(ret) <= uint8_t(category::UNKNOWN));
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum ircd::http::category
|
||||
ircd::http::category(const enum code &code)
|
||||
noexcept
|
||||
{
|
||||
if(ushort(code) == 0)
|
||||
return category::NONE;
|
||||
|
||||
if(ushort(code) < 200)
|
||||
return category::INFO;
|
||||
|
||||
if(ushort(code) < 300)
|
||||
return category::SUCCESS;
|
||||
|
||||
if(ushort(code) < 400)
|
||||
return category::REDIRECT;
|
||||
|
||||
if(ushort(code) < 500)
|
||||
return category::ERROR;
|
||||
|
||||
if(ushort(code) < 600)
|
||||
return category::SERVER;
|
||||
|
||||
return category::UNKNOWN;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::http::category(const enum category &category)
|
||||
noexcept
|
||||
{
|
||||
switch(category)
|
||||
{
|
||||
case category::NONE: return "NONE";
|
||||
case category::INFO: return "INFO";
|
||||
case category::SUCCESS: return "SUCCESS";
|
||||
case category::REDIRECT: return "REDIRECT";
|
||||
case category::ERROR: return "ERROR";
|
||||
case category::SERVER: return "SERVER";
|
||||
default:
|
||||
case category::UNKNOWN: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue