0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-11 06:28:55 +02:00

ircd::resource: Minor reorg class layout / opts.

This commit is contained in:
Jason Volk 2018-11-05 19:14:53 -08:00
parent cbbfbcac72
commit d49b3ba7dd
8 changed files with 98 additions and 78 deletions

View file

@ -33,8 +33,7 @@ struct ircd::resource
static std::map<string_view, resource *, iless> resources;
string_view path;
string_view description;
enum flag flags;
std::unique_ptr<const struct opts> opts;
std::map<string_view, method *> methods;
unique_const_iterator<decltype(resources)> resources_it;
@ -48,7 +47,7 @@ struct ircd::resource
void operator()(client &, const http::request::head &, const string_view &content_partial);
resource(const string_view &path, const opts &);
resource(const string_view &path, struct opts);
resource(const string_view &path);
resource() = default;
virtual ~resource() noexcept;
@ -84,6 +83,51 @@ struct ircd::resource::opts
};
};
struct ircd::resource::method
{
enum flag :uint;
struct opts;
using handler = std::function<response (client &, request &)>;
struct resource *resource;
string_view name;
handler function;
std::unique_ptr<const struct opts> opts;
unique_const_iterator<decltype(resource::methods)> methods_it;
public:
virtual response operator()(client &, request &);
method(struct resource &, const string_view &name, handler, struct opts);
method(struct resource &, const string_view &name, handler);
virtual ~method() noexcept;
};
enum ircd::resource::method::flag
:uint
{
REQUIRES_AUTH = 0x01,
RATE_LIMITED = 0x02,
VERIFY_ORIGIN = 0x04,
CONTENT_DISCRETION = 0x08,
};
struct ircd::resource::method::opts
{
flag flags {(flag)0};
/// Timeout specific to this resource.
seconds timeout {30s};
/// The maximum size of the Content-Length for this method. Anything
/// larger will be summarily rejected with a 413.
size_t payload_max {128_KiB};
/// MIME type; first part is the Registry (i.e application) and second
/// part is the format (i.e json). Empty value means nothing rejected.
std::pair<string_view, string_view> mime;
};
struct ircd::resource::request
:json::object
{
@ -185,45 +229,3 @@ struct ircd::resource::response::chunked
chunked() = default;
~chunked() noexcept;
};
struct ircd::resource::method
{
using handler = std::function<response (client &, request &)>;
enum flag
{
REQUIRES_AUTH = 0x01,
RATE_LIMITED = 0x02,
VERIFY_ORIGIN = 0x04,
CONTENT_DISCRETION = 0x08,
};
struct opts
{
flag flags {(flag)0};
/// Timeout specific to this resource.
seconds timeout {30s};
/// The maximum size of the Content-Length for this method. Anything
/// larger will be summarily rejected with a 413.
size_t payload_max {128_KiB};
/// MIME type; first part is the Registry (i.e application) and second
/// part is the format (i.e json). Empty value means nothing rejected.
std::pair<string_view, string_view> mime;
};
string_view name;
struct resource *resource;
handler function;
struct opts opts;
unique_const_iterator<decltype(resource::methods)> methods_it;
public:
virtual response operator()(client &, request &);
method(struct resource &, const string_view &name, const handler &, const struct opts &);
method(struct resource &, const string_view &name, const handler &);
virtual ~method() noexcept;
};

View file

@ -64,7 +64,7 @@ ircd::resource::find(const string_view &path_)
--it;
rpath = it->first;
if(~it->second->flags & it->second->DIRECTORY)
if(~it->second->opts->flags & it->second->DIRECTORY)
continue;
// If the closest directory still doesn't match hand this off to the
@ -75,13 +75,13 @@ ircd::resource::find(const string_view &path_)
// Check if the resource is a directory; if not, it can only
// handle exact path matches.
if(~it->second->flags & it->second->DIRECTORY && path != rpath)
if(~it->second->opts->flags & it->second->DIRECTORY && path != rpath)
throw http::error
{
http::code::NOT_FOUND
};
if(it->second->flags & it->second->DIRECTORY)
if(it->second->opts->flags & it->second->DIRECTORY)
{
const auto rem(lstrip(path, rpath));
if(!empty(rem) && !startswith(rem, '/'))
@ -101,19 +101,21 @@ ircd::resource::find(const string_view &path_)
ircd::resource::resource(const string_view &path)
:resource
{
path, opts{}
path, {}
}
{
}
ircd::resource::resource(const string_view &path,
const opts &opts)
struct opts opts)
:path
{
rstrip(path, '/')
}
,description{opts.description}
,flags{opts.flags}
,opts
{
std::make_unique<const struct opts>(std::move(opts))
}
,resources_it{[this]
{
const auto iit
@ -189,7 +191,7 @@ ircd::authenticate(client &client,
const bool requires_auth
{
method.opts.flags & method.REQUIRES_AUTH
method.opts->flags & method.REQUIRES_AUTH
};
if(!request.access_token && requires_auth)
@ -239,7 +241,7 @@ try
{
const bool required
{
method.opts.flags & method.VERIFY_ORIGIN
method.opts->flags & method.VERIFY_ORIGIN
};
const auto authorization
@ -360,7 +362,7 @@ ircd::resource::operator()(client &client,
};
// Bail out if the method limited the amount of content and it was exceeded.
if(head.content_length > method.opts.payload_max)
if(head.content_length > method.opts->payload_max)
throw http::error
{
http::PAYLOAD_TOO_LARGE
@ -368,12 +370,12 @@ ircd::resource::operator()(client &client,
// Check if the resource method wants a specific MIME type. If no option
// is given by the resource then any Content-Type by the client will pass.
if(method.opts.mime.first)
if(method.opts->mime.first)
{
const auto &ct(split(head.content_type, ';'));
const auto &supplied(split(ct.first, '/'));
const auto &charset(ct.second);
const auto &required(method.opts.mime);
const auto &required(method.opts->mime);
if(required.first != supplied.first
||(required.second && required.second != supplied.second))
throw http::error
@ -387,7 +389,7 @@ ircd::resource::operator()(client &client,
// disable this in its options structure.
const net::scope_timeout timeout
{
*client.sock, method.opts.timeout, [&client, &head]
*client.sock, method.opts->timeout, [&client, &head]
(const bool &timed_out)
{
if(!timed_out)
@ -433,7 +435,7 @@ ircd::resource::operator()(client &client,
content_partial
};
if(content_remain && ~method.opts.flags & method.CONTENT_DISCRETION)
if(content_remain && ~method.opts->flags & method.CONTENT_DISCRETION)
{
// Copy any partial content to the final contiguous allocated buffer;
client.content_buffer = unique_buffer<mutable_buffer>{head.content_length};
@ -585,24 +587,40 @@ ircd::resource::allow_methods_list(const mutable_buffer &buf)
return { data(buf), len };
}
//
// method::method
//
ircd::resource::method::method(struct resource &resource,
const string_view &name,
const handler &handler)
handler function)
:method
{
resource, name, handler, {}
resource, name, std::move(function), {}
}
{
}
ircd::resource::method::method(struct resource &resource,
const string_view &name,
const handler &handler,
const struct opts &opts)
:name{name}
,resource{&resource}
,function{handler}
,opts{opts}
handler function,
struct opts opts)
:resource
{
&resource
}
,name
{
name
}
,function
{
std::move(function)
}
,opts
{
std::make_unique<const struct opts>(std::move(opts))
}
,methods_it{[this, &name]
{
const auto iit

View file

@ -19,7 +19,7 @@ IRCD_MODULE
resource
join_resource
{
"/_matrix/client/r0/join/", resource::opts
"/_matrix/client/r0/join/",
{
"(7.4.2.3) Join room_id or alias.",
resource::DIRECTORY,

View file

@ -19,7 +19,7 @@ IRCD_MODULE
ircd::resource
keys_upload_resource
{
"/_matrix/client/unstable/keys/upload/", resource::opts
"/_matrix/client/unstable/keys/upload/",
{
"(11.10.2.1) Keys Upload",
resource::DIRECTORY,
@ -29,7 +29,7 @@ keys_upload_resource
ircd::resource
keys_query_resource
{
"/_matrix/client/unstable/keys/query", resource::opts
"/_matrix/client/unstable/keys/query",
{
"(11.10.2.2) Keys Query",
}

View file

@ -19,7 +19,7 @@ IRCD_MODULE
ircd::resource
presence_resource
{
"/_matrix/client/r0/presence/", resource::opts
"/_matrix/client/r0/presence/",
{
"(11.6.2) Presence",
resource::DIRECTORY,

View file

@ -19,7 +19,7 @@ IRCD_MODULE
ircd::resource
pushers_resource
{
"/_matrix/client/r0/pushers/", resource::opts
"/_matrix/client/r0/pushers/",
{
"(11.12.1) Pushers",
resource::DIRECTORY,

View file

@ -19,7 +19,7 @@ IRCD_MODULE
resource
versions_resource
{
"/_matrix/client/versions", resource::opts
"/_matrix/client/versions",
{
"(2.1) Gets the versions of the specification supported by the server."
}

View file

@ -3891,17 +3891,17 @@ console_cmd__resource(opt &out, const string_view &line)
{
const auto &r(*p.second);
out << '`' << p.first << '\''
<< (r.flags & resource::DIRECTORY? " DIRECTORY" : "")
<< (r.opts->flags & resource::DIRECTORY? " DIRECTORY" : "")
<< std::endl;
for(const auto &mp : p.second->methods)
{
const auto &m(*mp.second);
out << mp.first
<< (m.opts.flags & resource::method::REQUIRES_AUTH? " REQUIRES_AUTH" : "")
<< (m.opts.flags & resource::method::RATE_LIMITED? " RATE_LIMITED" : "")
<< (m.opts.flags & resource::method::VERIFY_ORIGIN? " VERIFY_ORIGIN" : "")
<< (m.opts.flags & resource::method::CONTENT_DISCRETION? " CONTENT_DISCRETION" : "")
<< (m.opts->flags & resource::method::REQUIRES_AUTH? " REQUIRES_AUTH" : "")
<< (m.opts->flags & resource::method::RATE_LIMITED? " RATE_LIMITED" : "")
<< (m.opts->flags & resource::method::VERIFY_ORIGIN? " VERIFY_ORIGIN" : "")
<< (m.opts->flags & resource::method::CONTENT_DISCRETION? " CONTENT_DISCRETION" : "")
<< std::endl;
}