168 lines
3.6 KiB
C++
168 lines
3.6 KiB
C++
#ifndef MEMGRAPH_SPEEDY_R3_HPP
|
|
#define MEMGRAPH_SPEEDY_R3_HPP
|
|
|
|
#include <list>
|
|
#include <cassert>
|
|
|
|
#include "request.hpp"
|
|
#include "response.hpp"
|
|
|
|
#include "utils/auto_scope.hpp"
|
|
#include "http/http.hpp"
|
|
|
|
namespace r3 {
|
|
#include "r3_include.h"
|
|
}
|
|
|
|
namespace sp
|
|
{
|
|
|
|
class R3Error : public std::runtime_error
|
|
{
|
|
public:
|
|
using runtime_error::runtime_error;
|
|
};
|
|
|
|
class R3
|
|
{
|
|
public:
|
|
enum Method : int
|
|
{
|
|
GET = METHOD_GET,
|
|
POST = METHOD_POST,
|
|
PUT = METHOD_PUT,
|
|
DELETE = METHOD_DELETE,
|
|
HEAD = METHOD_HEAD
|
|
};
|
|
|
|
static Method to_r3_method(http::Method method)
|
|
{
|
|
switch (method)
|
|
{
|
|
case http::Method::GET: return Method::GET;
|
|
case http::Method::POST: return Method::POST;
|
|
case http::Method::PUT: return Method::PUT;
|
|
case http::Method::DELETE: return Method::DELETE;
|
|
case http::Method::HEAD: return Method::HEAD;
|
|
}
|
|
}
|
|
|
|
private:
|
|
class MatchEntry
|
|
{
|
|
public:
|
|
MatchEntry(Method method, const std::string& path)
|
|
{
|
|
entry = r3::match_entry_createl(path.c_str(), path.size());
|
|
entry->request_method = method;
|
|
}
|
|
|
|
~MatchEntry()
|
|
{
|
|
r3::match_entry_free(entry);
|
|
}
|
|
|
|
operator r3::match_entry*()
|
|
{
|
|
return entry;
|
|
}
|
|
|
|
private:
|
|
r3::match_entry* entry;
|
|
r3::route* route;
|
|
};
|
|
|
|
public:
|
|
class Route
|
|
{
|
|
public:
|
|
Route(r3::route* route) : route(route) {}
|
|
|
|
bool exists() const
|
|
{
|
|
return route != nullptr;
|
|
}
|
|
|
|
void operator()(sp::Request& req, sp::Response& res)
|
|
{
|
|
assert(route != nullptr);
|
|
|
|
auto cb = reinterpret_cast<sp::request_cb_t*>(route->data);
|
|
cb->operator()(req, res);
|
|
}
|
|
|
|
private:
|
|
r3::route* route;
|
|
};
|
|
|
|
R3(size_t capacity)
|
|
{
|
|
root = r3::r3_tree_create(capacity);
|
|
}
|
|
|
|
~R3()
|
|
{
|
|
r3::r3_tree_free(root);
|
|
}
|
|
|
|
R3(R3&) = delete;
|
|
|
|
R3(R3&& other)
|
|
{
|
|
this->routes = std::move(other.routes);
|
|
this->root = other.root;
|
|
other.root = nullptr;
|
|
}
|
|
|
|
void insert(Method method, const std::string& path, sp::request_cb_t cb)
|
|
{
|
|
routes.push_back(cb);
|
|
|
|
r3::r3_tree_insert_routel(root, method, path.c_str(), path.size(),
|
|
&routes.back());
|
|
}
|
|
|
|
Route match(Method method, const std::string& path)
|
|
{
|
|
auto entry_m = MatchEntry(method, path);
|
|
return Route(r3::r3_tree_match_route(root, entry_m));
|
|
|
|
/* if(!route.exists()) */
|
|
/* return route; */
|
|
|
|
/* r3::match_entry* entry = entry_m; */
|
|
|
|
/* std::cout << "Eetry Matched!" << std::endl */
|
|
/* << "path = " << std::string(entry->path, entry->path_len) << std::endl */
|
|
/* << "host = " << std::string(entry->host, entry->host_len) << std::endl */
|
|
/* << "remote_addr = " << std::string(entry->remote_addr, entry->remote_addr_len) << std::endl */
|
|
/* << "tokens_len = " << entry->vars->len << std::endl; */
|
|
|
|
/* for(int i = 0; i < entry->vars->len; ++i) */
|
|
/* std::cout << "token " << i << " = " << std::string(entry->vars->tokens[i]) << std::endl; */
|
|
|
|
//return route;
|
|
}
|
|
|
|
void compile()
|
|
{
|
|
char* error_string = nullptr;
|
|
bool error = r3_tree_compile(root, &error_string);
|
|
|
|
if(!error)
|
|
return;
|
|
|
|
Auto(free(error_string));
|
|
|
|
throw R3Error(std::string(error_string));
|
|
}
|
|
|
|
private:
|
|
std::list<sp::request_cb_t> routes;
|
|
r3::node* root;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|