mirror of
https://github.com/matrix-construct/construct
synced 2025-01-14 00:34:18 +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,
|
NO_CONTENT = 204,
|
||||||
PARTIAL_CONTENT = 206,
|
PARTIAL_CONTENT = 206,
|
||||||
|
|
||||||
|
MULTIPLE_CHOICES = 300,
|
||||||
MOVED_PERMANENTLY = 301,
|
MOVED_PERMANENTLY = 301,
|
||||||
FOUND = 302,
|
FOUND = 302,
|
||||||
SEE_OTHER = 303,
|
SEE_OTHER = 303,
|
||||||
|
@ -114,6 +115,11 @@ struct ircd::http::line
|
||||||
line(parse::capstan &);
|
line(parse::capstan &);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ircd::http
|
||||||
|
{
|
||||||
|
using header = line::header;
|
||||||
|
}
|
||||||
|
|
||||||
struct ircd::http::line::request
|
struct ircd::http::line::request
|
||||||
{
|
{
|
||||||
string_view method;
|
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.
|
// HTTP headers are read once off the tape and proffered to the closure.
|
||||||
struct ircd::http::headers
|
struct ircd::http::headers
|
||||||
|
:string_view
|
||||||
{
|
{
|
||||||
using header = line::header;
|
using header = line::header;
|
||||||
using closure = std::function<void (const header &)>;
|
using closure = std::function<void (const header &)>;
|
||||||
|
@ -246,6 +253,8 @@ struct ircd::http::response::head
|
||||||
size_t content_length {0};
|
size_t content_length {0};
|
||||||
string_view transfer_encoding;
|
string_view transfer_encoding;
|
||||||
|
|
||||||
|
string_view headers;
|
||||||
|
|
||||||
head(parse::capstan &pc, const headers::closure &c = {});
|
head(parse::capstan &pc, const headers::closure &c = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,8 +306,11 @@ struct ircd::http::request::head
|
||||||
string_view host;
|
string_view host;
|
||||||
string_view expect;
|
string_view expect;
|
||||||
string_view te;
|
string_view te;
|
||||||
|
string_view authorization;
|
||||||
size_t content_length {0};
|
size_t content_length {0};
|
||||||
|
|
||||||
|
string_view headers;
|
||||||
|
|
||||||
head(parse::capstan &pc, const headers::closure &c = {});
|
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;
|
template<class it, class top = unused_type> struct grammar;
|
||||||
struct parser extern const parser;
|
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 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);
|
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::NO_CONTENT, "No Content" },
|
||||||
{ code::PARTIAL_CONTENT, "Partial Content" },
|
{ code::PARTIAL_CONTENT, "Partial Content" },
|
||||||
|
|
||||||
|
{ code::MULTIPLE_CHOICES, "Multiple Choices" },
|
||||||
{ code::MOVED_PERMANENTLY, "Moved Permanently" },
|
{ code::MOVED_PERMANENTLY, "Moved Permanently" },
|
||||||
{ code::FOUND, "Found" },
|
{ code::FOUND, "Found" },
|
||||||
{ code::SEE_OTHER, "See Other" },
|
{ 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,
|
ircd::http::request::head::head(parse::capstan &pc,
|
||||||
const headers::closure &c)
|
const headers::closure &c)
|
||||||
:line::request{pc}
|
: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))
|
if(iequals(h.first, "host"s))
|
||||||
host = h.second;
|
this->host = h.second;
|
||||||
else if(iequals(h.first, "expect"s))
|
else if(iequals(h.first, "expect"s))
|
||||||
expect = h.second;
|
this->expect = h.second;
|
||||||
else if(iequals(h.first, "te"s))
|
else if(iequals(h.first, "te"s))
|
||||||
te = h.second;
|
this->te = h.second;
|
||||||
else if(iequals(h.first, "content-length"s))
|
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)
|
if(c)
|
||||||
c(h);
|
c(h);
|
||||||
}};
|
}}
|
||||||
|
}
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::http::response::response(parse::capstan &pc,
|
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,
|
ircd::http::response::head::head(parse::capstan &pc,
|
||||||
const headers::closure &c)
|
const headers::closure &c)
|
||||||
:line::response{pc}
|
: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))
|
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))
|
else if(iequals(h.first, "transfer-encoding"s))
|
||||||
transfer_encoding = h.second;
|
this->transfer_encoding = h.second;
|
||||||
|
|
||||||
if(c)
|
if(c)
|
||||||
c(h);
|
c(h);
|
||||||
}};
|
}}
|
||||||
|
}
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::http::content::content(parse::capstan &pc,
|
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,
|
ircd::http::headers::headers(parse::capstan &pc,
|
||||||
const closure &c)
|
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)
|
if(c)
|
||||||
c(h);
|
c(h);
|
||||||
|
|
||||||
|
return { started, stopped };
|
||||||
|
}()}
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::http::line::header::header(const line &line)
|
ircd::http::line::header::header(const line &line)
|
||||||
|
@ -839,38 +858,6 @@ const
|
||||||
qi::parse(start, stop, grammar);
|
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
|
size_t
|
||||||
ircd::http::parser::content_length(const string_view &str)
|
ircd::http::parser::content_length(const string_view &str)
|
||||||
{
|
{
|
||||||
|
@ -888,12 +875,6 @@ ircd::http::parser::content_length(const string_view &str)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ircd::http
|
|
||||||
{
|
|
||||||
struct urlencoder extern const urlencoder;
|
|
||||||
struct urldecoder extern const urldecoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ircd::http::urlencoder
|
struct ircd::http::urlencoder
|
||||||
:karma::grammar<char *, const string_view &>
|
: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);
|
karma::generate(out, maxwidth(size(buf))[urlencoder], url);
|
||||||
return string_view{data(buf), size_t(std::distance(data(buf), out))};
|
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