0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-27 07:54:05 +01:00

ircd::http: Add more functionality to headers class.

This commit is contained in:
Jason Volk 2018-12-31 11:06:18 -08:00
parent 27bd661e5a
commit 57079c0276
2 changed files with 125 additions and 14 deletions

View file

@ -30,11 +30,12 @@ namespace ircd::http
void writeline(window_buffer &, const window_buffer::closure &); void writeline(window_buffer &, const window_buffer::closure &);
void write(window_buffer &, const header &); void write(window_buffer &, const header &);
void write(window_buffer &, const vector_view<const header> &); void write(window_buffer &, const vector_view<const header> &);
bool has(const vector_view<const header> &, const string_view &key);
size_t serialized(const vector_view<const header> &); size_t serialized(const vector_view<const header> &);
std::string strung(const vector_view<const header> &); std::string strung(const vector_view<const header> &);
void writechunk(window_buffer &, const uint32_t &size); void writechunk(window_buffer &, const uint32_t &size);
const_buffer writechunk(const mutable_buffer &, const uint32_t &size); const_buffer writechunk(const mutable_buffer &, const uint32_t &size);
bool has(const headers &, const string_view &key);
bool has(const vector_view<const header> &, const string_view &key);
} }
/// Root exception for HTTP. /// Root exception for HTTP.
@ -158,6 +159,7 @@ struct ircd::http::header
{ {
bool operator<(const string_view &s) const { return iless(first, s); } bool operator<(const string_view &s) const { return iless(first, s); }
bool operator==(const string_view &s) const { return iequals(first, s); } bool operator==(const string_view &s) const { return iequals(first, s); }
bool operator!=(const string_view &s) const { return !operator==(s); }
using std::pair<string_view, string_view>::pair; using std::pair<string_view, string_view>::pair;
header(const line &); header(const line &);
@ -174,8 +176,20 @@ struct ircd::http::headers
:string_view :string_view
{ {
using closure = std::function<void (const header &)>; using closure = std::function<void (const header &)>;
using closure_bool = std::function<bool (const header &)>;
bool for_each(const closure_bool &) const;
string_view operator[](const string_view &key) const;
string_view at(const string_view &key) const;
bool has(const string_view &key) const;
using string_view::string_view;
headers(parse::capstan &, closure_bool);
headers(parse::capstan &, const closure & = {}); headers(parse::capstan &, const closure & = {});
headers() = default;
friend bool has(const headers &, const string_view &key);
friend bool has(const vector_view<const header> &, const string_view &key);
}; };
/// HTTP request suite. Functionality to send and receive requests. /// HTTP request suite. Functionality to send and receive requests.

View file

@ -428,22 +428,130 @@ catch(const qi::expectation_failure<const char *> &e)
throw_error(e, true); throw_error(e, true);
} }
//
// headers
//
bool
ircd::http::has(const vector_view<const header> &headers,
const string_view &key)
{
return end(headers) != std::find_if(begin(headers), end(headers), [&key]
(const header &header)
{
return header == key;
});
}
bool
ircd::http::has(const headers &headers,
const string_view &key)
{
return headers.has(key);
}
//
// headers::headers
//
ircd::http::headers::headers(parse::capstan &pc, ircd::http::headers::headers(parse::capstan &pc,
const closure &c) const closure &c)
:headers
{
pc, closure_bool{[&c](const auto &header)
{
if(c)
c(header);
return true;
}}
}
{
}
ircd::http::headers::headers(parse::capstan &pc,
closure_bool c)
:string_view{[&pc, &c] :string_view{[&pc, &c]
() -> string_view () -> string_view
{ {
header h{pc}; header h{pc};
const char *const &started{h.first.data()}, *stopped{started}; const char *const &started{h.first.data()}, *stopped{started};
for(; !h.first.empty(); stopped = h.second.data() + h.second.size(), h = header{pc}) for(; !h.first.empty(); stopped = h.second.data() + h.second.size(), h = header{pc})
if(c) if(c && !c(h))
c(h); c = {};
return { started, stopped }; return { started, stopped };
}()} }()}
{ {
} }
bool
ircd::http::headers::has(const string_view &key)
const
{
// has header if break early from for_each
return !for_each([&key]
(const header &header)
{
// true to continue; false to break (for_each protocol)
return header != key;
});
}
ircd::string_view
ircd::http::headers::at(const string_view &key)
const
{
const string_view ret
{
this->operator[](key)
};
if(unlikely(!ret))
throw std::out_of_range{key};
return ret;
}
ircd::string_view
ircd::http::headers::operator[](const string_view &key)
const
{
string_view ret;
for_each([&key, &ret](const auto &header)
{
if(header == key)
{
ret = header.second;
return false;
}
else return true;
});
return ret;
}
bool
ircd::http::headers::for_each(const closure_bool &closure)
const
{
if(empty())
return true;
parse::buffer pb{const_buffer{*this}};
parse::capstan pc{pb};
header h{pc};
for(; !h.first.empty(); h = header{pc})
if(!closure(h))
return false;
return true;
}
//
// header
//
ircd::http::header::header(const line &line) ircd::http::header::header(const line &line)
try try
{ {
@ -617,17 +725,6 @@ ircd::http::writechunk(window_buffer &buf,
}); });
} }
bool
ircd::http::has(const vector_view<const header> &headers,
const string_view &key)
{
return end(headers) != std::find_if(begin(headers), end(headers), [&key]
(const header &header)
{
return iequals(header.first, key);
});
}
std::string std::string
ircd::http::strung(const vector_view<const header> &headers) ircd::http::strung(const vector_view<const header> &headers)
{ {