2016-11-29 16:23:38 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Charybdis Development Team
|
|
|
|
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice is present in all copies.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#define HAVE_IRCD_RESOURCE_H
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
namespace ircd
|
|
|
|
{
|
|
|
|
struct resource;
|
|
|
|
}
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::resource
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
IRCD_EXCEPTION(ircd::error, error)
|
|
|
|
|
2017-12-12 21:26:39 +01:00
|
|
|
enum flag :uint;
|
|
|
|
struct opts;
|
2016-11-29 16:23:38 +01:00
|
|
|
struct method;
|
|
|
|
struct request;
|
|
|
|
struct response;
|
|
|
|
|
2017-08-23 23:06:14 +02:00
|
|
|
static std::map<string_view, resource *, iless> resources;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-08-23 23:06:14 +02:00
|
|
|
string_view path;
|
|
|
|
string_view description;
|
2017-12-12 21:26:39 +01:00
|
|
|
enum flag flags;
|
2017-08-23 23:06:14 +02:00
|
|
|
std::map<string_view, method *> methods;
|
|
|
|
unique_const_iterator<decltype(resources)> resources_it;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-08-23 23:06:14 +02:00
|
|
|
private:
|
|
|
|
virtual void handle_request(client &, method &, resource::request &);
|
2017-03-21 03:30:07 +01:00
|
|
|
|
2016-11-29 16:23:38 +01:00
|
|
|
public:
|
2017-08-23 23:06:14 +02:00
|
|
|
method &operator[](const string_view &path);
|
2018-01-12 03:45:25 +01:00
|
|
|
|
|
|
|
void operator()(client &,
|
|
|
|
const http::request::head &,
|
|
|
|
const string_view &content_partial,
|
|
|
|
size_t &content_consumed);
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-12-12 21:26:39 +01:00
|
|
|
resource(const string_view &path, const opts &);
|
|
|
|
resource(const string_view &path);
|
2017-08-23 23:06:14 +02:00
|
|
|
resource() = default;
|
2016-11-29 16:23:38 +01:00
|
|
|
virtual ~resource() noexcept;
|
2017-08-23 23:06:14 +02:00
|
|
|
|
|
|
|
static resource &find(string_view path);
|
2016-11-29 16:23:38 +01:00
|
|
|
};
|
|
|
|
|
2017-12-12 21:26:39 +01:00
|
|
|
enum ircd::resource::flag
|
|
|
|
:uint
|
|
|
|
{
|
|
|
|
DIRECTORY = 0x01,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ircd::resource::opts
|
|
|
|
{
|
|
|
|
/// developer's literal description of the resource
|
|
|
|
string_view description
|
|
|
|
{
|
|
|
|
"no description"
|
|
|
|
};
|
|
|
|
|
|
|
|
/// flags for the resource
|
|
|
|
flag flags
|
|
|
|
{
|
|
|
|
flag(0)
|
|
|
|
};
|
|
|
|
|
|
|
|
/// parameter count limits (DIRECTORY only)
|
|
|
|
std::pair<short, short> parc
|
|
|
|
{
|
|
|
|
0, // minimum params
|
|
|
|
15 // maximum params
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::resource::request
|
2017-08-23 23:47:21 +02:00
|
|
|
:json::object
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
2017-09-21 11:11:07 +02:00
|
|
|
template<class> struct object;
|
2017-08-28 23:51:22 +02:00
|
|
|
|
2016-11-29 16:23:38 +01:00
|
|
|
const http::request::head &head;
|
2018-01-12 03:45:25 +01:00
|
|
|
string_view content;
|
2017-08-23 23:06:14 +02:00
|
|
|
http::query::string query;
|
2017-12-12 21:26:39 +01:00
|
|
|
string_view user_id; //m::user::id::buf user_id; //TODO: bleeding
|
2017-10-12 05:52:33 +02:00
|
|
|
vector_view<string_view> parv;
|
2017-03-21 03:30:07 +01:00
|
|
|
|
2018-01-12 03:45:25 +01:00
|
|
|
request(const http::request::head &head,
|
|
|
|
const string_view &content,
|
|
|
|
http::query::string query,
|
|
|
|
const vector_view<string_view> &parv);
|
2017-03-21 03:30:07 +01:00
|
|
|
};
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
template<class tuple>
|
2017-09-21 11:11:07 +02:00
|
|
|
struct ircd::resource::request::object
|
2017-08-28 23:51:22 +02:00
|
|
|
:tuple
|
|
|
|
{
|
2017-09-21 11:11:07 +02:00
|
|
|
resource::request &r;
|
|
|
|
const http::request::head &head;
|
2018-01-12 03:45:25 +01:00
|
|
|
const string_view &content;
|
2017-09-21 11:11:07 +02:00
|
|
|
const http::query::string &query;
|
2017-12-12 21:26:39 +01:00
|
|
|
const decltype(r.user_id) &user_id;
|
2017-10-12 05:52:33 +02:00
|
|
|
const vector_view<string_view> &parv;
|
2017-09-21 11:11:07 +02:00
|
|
|
const json::object &body;
|
|
|
|
|
|
|
|
object(resource::request &r)
|
|
|
|
:tuple{r}
|
|
|
|
,r{r}
|
|
|
|
,head{r.head}
|
|
|
|
,content{r.content}
|
|
|
|
,query{r.query}
|
2017-12-12 21:26:39 +01:00
|
|
|
,user_id{r.user_id}
|
2017-10-12 05:52:33 +02:00
|
|
|
,parv{r.parv}
|
2017-09-21 11:11:07 +02:00
|
|
|
,body{r}
|
|
|
|
{}
|
2017-08-28 23:51:22 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ircd::resource::response
|
2017-03-21 03:30:07 +01:00
|
|
|
{
|
2017-12-24 22:25:09 +01:00
|
|
|
response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view<const http::header> &);
|
|
|
|
response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {});
|
2017-09-15 21:07:07 +02:00
|
|
|
response(client &, const json::object &str, const http::code & = http::OK);
|
2017-09-25 02:00:05 +02:00
|
|
|
response(client &, const json::array &str, const http::code & = http::OK);
|
2017-09-15 21:07:07 +02:00
|
|
|
response(client &, const json::members & = {}, const http::code & = http::OK);
|
2017-09-25 02:00:05 +02:00
|
|
|
response(client &, const json::value &, const http::code & = http::OK);
|
2017-09-09 21:20:00 +02:00
|
|
|
response(client &, const json::iov &, const http::code & = http::OK);
|
2017-09-12 22:34:21 +02:00
|
|
|
response(client &, const http::code &, const json::members &);
|
2017-09-25 02:00:05 +02:00
|
|
|
response(client &, const http::code &, const json::value &);
|
2017-09-09 21:20:00 +02:00
|
|
|
response(client &, const http::code &, const json::iov &);
|
|
|
|
response(client &, const http::code &);
|
2017-03-21 03:30:07 +01:00
|
|
|
response() = default;
|
2016-11-29 16:23:38 +01:00
|
|
|
};
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::resource::method
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
2018-01-12 03:45:25 +01:00
|
|
|
using handler = std::function<response (client &, request &)>;
|
|
|
|
|
2017-08-23 23:06:14 +02:00
|
|
|
enum flag
|
|
|
|
{
|
|
|
|
REQUIRES_AUTH = 0x01,
|
|
|
|
RATE_LIMITED = 0x02,
|
2017-10-16 06:29:38 +02:00
|
|
|
VERIFY_ORIGIN = 0x04,
|
2017-08-23 23:06:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct opts
|
|
|
|
{
|
2018-01-12 03:45:25 +01:00
|
|
|
flag flags {(flag)0};
|
2017-08-23 23:06:14 +02:00
|
|
|
|
2018-01-12 03:45:25 +01:00
|
|
|
/// 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};
|
|
|
|
};
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-08-23 23:06:14 +02:00
|
|
|
string_view name;
|
2016-11-29 16:23:38 +01:00
|
|
|
struct resource *resource;
|
2017-08-23 23:06:14 +02:00
|
|
|
handler function;
|
2018-01-12 03:45:25 +01:00
|
|
|
struct opts opts;
|
2017-08-23 23:06:14 +02:00
|
|
|
unique_const_iterator<decltype(resource::methods)> methods_it;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
|
|
|
public:
|
2017-08-23 23:06:14 +02:00
|
|
|
virtual response operator()(client &, request &);
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-01-12 03:45:25 +01:00
|
|
|
method(struct resource &, const string_view &name, const handler &, const struct opts &);
|
|
|
|
method(struct resource &, const string_view &name, const handler &);
|
2017-08-23 23:06:14 +02:00
|
|
|
virtual ~method() noexcept;
|
2016-11-29 16:23:38 +01:00
|
|
|
};
|