fixed speedy
This commit is contained in:
parent
61241ba039
commit
71dad5a6af
127
speedy/r3.hpp
Normal file
127
speedy/r3.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
#ifndef MEMGRAPH_SPEEDY_R3_HPP
|
||||
#define MEMGRAPH_SPEEDY_R3_HPP
|
||||
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
||||
#include "http/http.hpp"
|
||||
|
||||
namespace r3 {
|
||||
#include "r3_include.h"
|
||||
}
|
||||
|
||||
namespace speedy
|
||||
{
|
||||
|
||||
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()(http::Request& req, http::Response& res)
|
||||
{
|
||||
assert(route != nullptr);
|
||||
|
||||
auto cb = reinterpret_cast<http::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->root = other.root;
|
||||
other.root = nullptr;
|
||||
}
|
||||
|
||||
void insert(Method method, const std::string& path, http::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 = MatchEntry(method, path);
|
||||
return Route(r3::r3_tree_match_route(root, entry));
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<http::request_cb_t> routes;
|
||||
r3::node* root;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -7,68 +7,61 @@
|
||||
* @author Dominik Tomicevic (domko)
|
||||
* @author Marko Budiselic (buda)
|
||||
*/
|
||||
#ifndef MEMGRAPH_SPEEDY_HPP
|
||||
#define MEMGRAPH_SPEEDY_HPP
|
||||
#ifndef MEMGRAPH_SPEEDY_SPEEDY_HPP
|
||||
#define MEMGRAPH_SPEEDY_SPEEDY_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "io/uv/uv.hpp"
|
||||
#include "http/http.hpp"
|
||||
#include "r3_include.h"
|
||||
#include "r3.hpp"
|
||||
|
||||
namespace speedy
|
||||
{
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
class Speedy
|
||||
{
|
||||
private:
|
||||
/*
|
||||
* http server instance that contains all logic related
|
||||
* to the http protocol
|
||||
*/
|
||||
http::HttpServer server;
|
||||
|
||||
/*
|
||||
* ip address of the server
|
||||
*/
|
||||
http::Ipv4 ip;
|
||||
|
||||
/*
|
||||
* root node of r3 decision tree
|
||||
*/
|
||||
node *n;
|
||||
|
||||
/*
|
||||
* callbacks container
|
||||
*/
|
||||
std::vector<http::request_cb_t> callbacks;
|
||||
|
||||
/** @brief Store a http callback.
|
||||
*
|
||||
* Every callback for now has receiving method and path (url).
|
||||
* So, the implementation of this method saves callback for
|
||||
* the method and the path.
|
||||
*
|
||||
* @param method int http defined method
|
||||
* @param path std::string path (url)
|
||||
* @param callback http::request_cb_t callback which will be called
|
||||
* on a http request
|
||||
*/
|
||||
void store_callback(int method,
|
||||
const std::string &path,
|
||||
http::request_cb_t callback);
|
||||
public:
|
||||
Speedy(uv::UvLoop& loop, const http::Ipv4& ip);
|
||||
void get(const std::string &path, http::request_cb_t callback);
|
||||
void post(const std::string &path, http::request_cb_t callback);
|
||||
void put(const std::string &path, http::request_cb_t callback);
|
||||
void del(const std::string &path, http::request_cb_t callback);
|
||||
void listen();
|
||||
Speedy(uv::UvLoop& loop) : server(loop), router(100) {}
|
||||
|
||||
Speedy(Speedy&) = delete;
|
||||
Speedy(Speedy&&) = delete;
|
||||
|
||||
void get(const std::string& path, http::request_cb_t cb)
|
||||
{
|
||||
router.insert(R3::Method::GET, path, cb);
|
||||
}
|
||||
|
||||
void post(const std::string& path, http::request_cb_t cb)
|
||||
{
|
||||
router.insert(R3::Method::POST, path, cb);
|
||||
}
|
||||
|
||||
void put(const std::string& path, http::request_cb_t cb)
|
||||
{
|
||||
router.insert(R3::Method::PUT, path, cb);
|
||||
}
|
||||
|
||||
void del(const std::string& path, http::request_cb_t cb)
|
||||
{
|
||||
router.insert(R3::Method::DELETE, path, cb);
|
||||
}
|
||||
|
||||
void listen(const http::Ipv4& ip)
|
||||
{
|
||||
server.listen(ip, [this](http::Request& req, http::Response& res) {
|
||||
auto route = router.match(R3::to_r3_method(req.method), req.url);
|
||||
|
||||
if(!route.exists())
|
||||
return res.send(http::Status::NotFound, "Resource not found");
|
||||
|
||||
route(req, res);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
http::HttpServer server;
|
||||
R3 router;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "speedy.inl"
|
||||
|
||||
#endif
|
||||
|
@ -1,95 +0,0 @@
|
||||
#ifndef MEMGRAPH_SPEEDY_INL
|
||||
#define MEMGRAPH_SPEEDY_INL
|
||||
|
||||
#include "speedy.hpp"
|
||||
#include <http_parser.h>
|
||||
|
||||
namespace speedy
|
||||
{
|
||||
|
||||
int r3_request_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;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: better implementation
|
||||
|
||||
Speedy::Speedy(uv::UvLoop& loop, const http::Ipv4& ip) : server(loop), ip(ip)
|
||||
{
|
||||
n = r3_tree_create(100);
|
||||
}
|
||||
|
||||
void Speedy::store_callback(int method,
|
||||
const std::string &path,
|
||||
http::request_cb_t callback)
|
||||
{
|
||||
callbacks.push_back(callback);
|
||||
void *ptr = malloc(sizeof(uint));
|
||||
*((uint *)ptr) = callbacks.size() - 1;
|
||||
r3_tree_insert_routel(n, method, path.c_str(), path.size(), ptr);
|
||||
}
|
||||
|
||||
void Speedy::get(const std::string &path, http::request_cb_t callback)
|
||||
{
|
||||
store_callback(METHOD_GET, path, callback);
|
||||
|
||||
// TODO: something like this
|
||||
// this solution doesn't work, currenlty I don't know why
|
||||
// callbacks.push_back(callback)
|
||||
// r3_tree_insert_pathl(n, path.c_str(), path.size(), &callbacks.back());
|
||||
}
|
||||
|
||||
void Speedy::post(const std::string &path, http::request_cb_t callback)
|
||||
{
|
||||
store_callback(METHOD_POST, path, callback);
|
||||
}
|
||||
|
||||
void Speedy::put(const std::string &path, http::request_cb_t callback)
|
||||
{
|
||||
store_callback(METHOD_PUT, path, callback);
|
||||
}
|
||||
|
||||
void Speedy::del(const std::string &path, http::request_cb_t callback)
|
||||
{
|
||||
store_callback(METHOD_DELETE, path, callback);
|
||||
}
|
||||
|
||||
void Speedy::listen()
|
||||
{
|
||||
char *errstr = NULL;
|
||||
int err = r3_tree_compile(n, &errstr);
|
||||
if (err) {
|
||||
std::cout << "R3 compile error" << std::endl;
|
||||
}
|
||||
|
||||
server.listen(ip, [this](http::Request& req, http::Response& res) {
|
||||
auto url = req.url;
|
||||
auto c_url = url.c_str();
|
||||
match_entry *entry = match_entry_create(c_url);
|
||||
entry->request_method = r3_request_method(req.method);
|
||||
route *r = r3_tree_match_route(this->n, entry);
|
||||
match_entry_free(entry);
|
||||
if (r) {
|
||||
int index = *((int *)r->data);
|
||||
auto callback = this->callbacks[index];
|
||||
callback(req, res);
|
||||
// TODO: and something like this
|
||||
// auto callback = *reinterpret_cast<http::request_cb_t*>(n->data);
|
||||
// callback(req, res);
|
||||
} else {
|
||||
res.send("Not found");
|
||||
}
|
||||
});
|
||||
|
||||
std::cout << "Server is UP" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -32,7 +32,7 @@ int main(void)
|
||||
// speedy init
|
||||
uv::UvLoop loop;
|
||||
http::Ipv4 ip("0.0.0.0", 3400);
|
||||
speedy::Speedy app(loop, ip);
|
||||
speedy::Speedy app(loop);
|
||||
|
||||
// GET methods
|
||||
app.get(test_url_1, test_callback);
|
||||
@ -60,7 +60,7 @@ int main(void)
|
||||
test_delete(test_callback, app);
|
||||
|
||||
// app run
|
||||
app.listen();
|
||||
app.listen(ip);
|
||||
loop.run(uv::UvLoop::Mode::Default);
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user