mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 07:23:53 +01:00
ircd::http: Add authorization; multiple-choices error; improve header proffer; cleanup/reorg.
This commit is contained in:
parent
908fde12c4
commit
045d38d034
2 changed files with 74 additions and 49 deletions
|
@ -66,6 +66,7 @@ enum ircd::http::code
|
|||
NO_CONTENT = 204,
|
||||
PARTIAL_CONTENT = 206,
|
||||
|
||||
MULTIPLE_CHOICES = 300,
|
||||
MOVED_PERMANENTLY = 301,
|
||||
FOUND = 302,
|
||||
SEE_OTHER = 303,
|
||||
|
@ -114,6 +115,11 @@ struct ircd::http::line
|
|||
line(parse::capstan &);
|
||||
};
|
||||
|
||||
namespace ircd::http
|
||||
{
|
||||
using header = line::header;
|
||||
}
|
||||
|
||||
struct ircd::http::line::request
|
||||
{
|
||||
string_view method;
|
||||
|
@ -175,6 +181,7 @@ struct ircd::http::line::header
|
|||
|
||||
// HTTP headers are read once off the tape and proffered to the closure.
|
||||
struct ircd::http::headers
|
||||
:string_view
|
||||
{
|
||||
using header = line::header;
|
||||
using closure = std::function<void (const header &)>;
|
||||
|
@ -246,6 +253,8 @@ struct ircd::http::response::head
|
|||
size_t content_length {0};
|
||||
string_view transfer_encoding;
|
||||
|
||||
string_view headers;
|
||||
|
||||
head(parse::capstan &pc, const headers::closure &c = {});
|
||||
};
|
||||
|
||||
|
@ -297,8 +306,11 @@ struct ircd::http::request::head
|
|||
string_view host;
|
||||
string_view expect;
|
||||
string_view te;
|
||||
string_view authorization;
|
||||
size_t content_length {0};
|
||||
|
||||
string_view headers;
|
||||
|
||||
head(parse::capstan &pc, const headers::closure &c = {});
|
||||
};
|
||||
|
||||
|
|
111
ircd/http.cc
111
ircd/http.cc
|
@ -47,6 +47,8 @@ namespace ircd::http
|
|||
|
||||
template<class it, class top = unused_type> struct grammar;
|
||||
struct parser extern const parser;
|
||||
struct urlencoder extern const urlencoder;
|
||||
struct urldecoder extern const urldecoder;
|
||||
|
||||
size_t printed_size(const vector_view<const line::header> &headers);
|
||||
size_t print(char *const &buf, const size_t &max, const vector_view<const line::header> &headers);
|
||||
|
@ -66,6 +68,7 @@ const decltype(ircd::http::reason) ircd::http::reason
|
|||
{ code::NO_CONTENT, "No Content" },
|
||||
{ code::PARTIAL_CONTENT, "Partial Content" },
|
||||
|
||||
{ code::MULTIPLE_CHOICES, "Multiple Choices" },
|
||||
{ code::MOVED_PERMANENTLY, "Moved Permanently" },
|
||||
{ code::FOUND, "Found" },
|
||||
{ code::SEE_OTHER, "See Other" },
|
||||
|
@ -364,21 +367,26 @@ ircd::http::request::request(const string_view &host,
|
|||
ircd::http::request::head::head(parse::capstan &pc,
|
||||
const headers::closure &c)
|
||||
:line::request{pc}
|
||||
,headers
|
||||
{
|
||||
headers{pc, [this, &c](const auto &h)
|
||||
http::headers{pc, [this, &c](const auto &h)
|
||||
{
|
||||
if(iequals(h.first, "host"s))
|
||||
host = h.second;
|
||||
this->host = h.second;
|
||||
else if(iequals(h.first, "expect"s))
|
||||
expect = h.second;
|
||||
this->expect = h.second;
|
||||
else if(iequals(h.first, "te"s))
|
||||
te = h.second;
|
||||
this->te = h.second;
|
||||
else if(iequals(h.first, "content-length"s))
|
||||
content_length = parser.content_length(h.second);
|
||||
this->content_length = parser.content_length(h.second);
|
||||
else if(iequals(h.first, "authorization"s))
|
||||
this->authorization = h.second;
|
||||
|
||||
if(c)
|
||||
c(h);
|
||||
}};
|
||||
}}
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::http::response::response(parse::capstan &pc,
|
||||
|
@ -545,18 +553,21 @@ ircd::http::response::chunked::chunk::chunk(chunked &chunked,
|
|||
ircd::http::response::head::head(parse::capstan &pc,
|
||||
const headers::closure &c)
|
||||
:line::response{pc}
|
||||
,headers
|
||||
{
|
||||
headers{pc, [this, &c](const auto &h)
|
||||
http::headers{pc, [this, &c](const auto &h)
|
||||
{
|
||||
if(iequals(h.first, "content-length"s))
|
||||
content_length = parser.content_length(h.second);
|
||||
this->content_length = parser.content_length(h.second);
|
||||
|
||||
else if(iequals(h.first, "transfer-encoding"s))
|
||||
transfer_encoding = h.second;
|
||||
this->transfer_encoding = h.second;
|
||||
|
||||
if(c)
|
||||
c(h);
|
||||
}};
|
||||
}}
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::http::content::content(parse::capstan &pc,
|
||||
|
@ -662,10 +673,18 @@ ircd::http::content::content(parse::capstan &pc,
|
|||
|
||||
ircd::http::headers::headers(parse::capstan &pc,
|
||||
const closure &c)
|
||||
:string_view{[&pc, &c]
|
||||
() -> string_view
|
||||
{
|
||||
for(line::header h{pc}; !h.first.empty(); h = line::header{pc})
|
||||
line::header h{pc};
|
||||
const char *const &started{h.first.data()}, *stopped{started};
|
||||
for(; !h.first.empty(); stopped = h.second.data() + h.second.size(), h = line::header{pc})
|
||||
if(c)
|
||||
c(h);
|
||||
|
||||
return { started, stopped };
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::http::line::header::header(const line &line)
|
||||
|
@ -839,38 +858,6 @@ const
|
|||
qi::parse(start, stop, grammar);
|
||||
}
|
||||
|
||||
ircd::http::error::error(const enum code &code,
|
||||
std::string content)
|
||||
:ircd::error{generate_skip}
|
||||
,code{code}
|
||||
,content{std::move(content)}
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%d %s", int(code), status(code).data());
|
||||
}
|
||||
|
||||
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 bool parsed(qi::parse(start, start + str.size(), grammar, ret));
|
||||
if(!parsed || ret < 0 || ret >= 1000)
|
||||
throw ircd::error("Invalid HTTP status code");
|
||||
|
||||
return http::code(ret);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::http::status(const enum code &code)
|
||||
{
|
||||
return reason.at(code);
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::http::parser::content_length(const string_view &str)
|
||||
{
|
||||
|
@ -888,12 +875,6 @@ ircd::http::parser::content_length(const string_view &str)
|
|||
return ret;
|
||||
}
|
||||
|
||||
namespace ircd::http
|
||||
{
|
||||
struct urlencoder extern const urlencoder;
|
||||
struct urldecoder extern const urldecoder;
|
||||
}
|
||||
|
||||
struct ircd::http::urlencoder
|
||||
:karma::grammar<char *, const string_view &>
|
||||
{
|
||||
|
@ -987,3 +968,35 @@ ircd::http::urlencode(const string_view &url,
|
|||
karma::generate(out, maxwidth(size(buf))[urlencoder], url);
|
||||
return string_view{data(buf), size_t(std::distance(data(buf), out))};
|
||||
}
|
||||
|
||||
ircd::http::error::error(const enum code &code,
|
||||
std::string content)
|
||||
:ircd::error{generate_skip}
|
||||
,code{code}
|
||||
,content{std::move(content)}
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%d %s", int(code), status(code).data());
|
||||
}
|
||||
|
||||
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 bool parsed(qi::parse(start, start + str.size(), grammar, ret));
|
||||
if(!parsed || ret < 0 || ret >= 1000)
|
||||
throw ircd::error("Invalid HTTP status code");
|
||||
|
||||
return http::code(ret);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::http::status(const enum code &code)
|
||||
{
|
||||
return reason.at(code);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue