From 474492ddadb076eac4de33764e11e601921e22c0 Mon Sep 17 00:00:00 2001 From: buda <mbudiselicbuda@gmail.com> Date: Thu, 24 Sep 2015 01:00:02 +0200 Subject: [PATCH] speedy: first let say usefull implementation, GET, POST, PUT, DELETE methods are implemented --- speedy/.gitignore | 3 +++ speedy/Makefile | 3 ++- speedy/speedy.hpp | 9 ++++++- speedy/speedy.inl | 63 +++++++++++++++++++++++++++++++++++++++++------ speedy/test.cpp | 62 +++++++++++++++++++++++++++++++++++----------- speedy/test.py | 22 +++++++++++++++++ 6 files changed, 138 insertions(+), 24 deletions(-) create mode 100644 speedy/test.py diff --git a/speedy/.gitignore b/speedy/.gitignore index f47cb2045..bd250b222 100644 --- a/speedy/.gitignore +++ b/speedy/.gitignore @@ -1 +1,4 @@ *.out +*.dSYM/ +*.gdb +.gdb_history diff --git a/speedy/Makefile b/speedy/Makefile index 62e9fad6f..98078a83b 100644 --- a/speedy/Makefile +++ b/speedy/Makefile @@ -1,7 +1,8 @@ CXX=clang++ CFLAGS=-std=c++11 -Wall LDFLAGS=-luv -lhttp_parser -lr3 -INC=-I../ +# debug only +INC=-I../ -g -O0 -fno-inline-functions SOURCES=$(wildcard *.cpp) EXECUTABLE=test.out # OBJECTS=$(SOURCES:.cpp=.o) diff --git a/speedy/speedy.hpp b/speedy/speedy.hpp index 3f7ae2b6f..cc17b7bd5 100644 --- a/speedy/speedy.hpp +++ b/speedy/speedy.hpp @@ -10,15 +10,22 @@ namespace speedy { +typedef unsigned int uint; + class Speedy { private: http::HttpServer server; http::Ipv4 ip; node *n; + std::vector<http::request_cb_t> callbacks; + void store_index(int method, const std::string &path); public: Speedy(uv::UvLoop& loop, const http::Ipv4& ip); - void get(const std::string &path, http::request_cb_t callback); + 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(); }; diff --git a/speedy/speedy.inl b/speedy/speedy.inl index 7e8a50aee..b56d7cd60 100644 --- a/speedy/speedy.inl +++ b/speedy/speedy.inl @@ -2,23 +2,64 @@ #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_index(int method, const std::string &path) +{ + 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) { - // this->callbacks.push_back(callback); - // r3_tree_insert_pathl(n, path.c_str(), path.size(), &callbacks[callbacks.size() - 1]); - r3_tree_insert_pathl(n, path.c_str(), path.size(), &callback); + callbacks.push_back(callback); + store_index(METHOD_GET, path); + + // TODO: something like this + // this solution doesn't work, currenlty I don't know why // r3_tree_insert_pathl(n, path.c_str(), path.size(), &callbacks.back()); } +void Speedy::post(const std::string &path, http::request_cb_t callback) +{ + callbacks.push_back(callback); + store_index(METHOD_POST, path); +} + +void Speedy::put(const std::string &path, http::request_cb_t callback) +{ + callbacks.push_back(callback); + store_index(METHOD_PUT, path); +} + +void Speedy::del(const std::string &path, http::request_cb_t callback) +{ + callbacks.push_back(callback); + store_index(METHOD_DELETE, path); +} + void Speedy::listen() { char *errstr = NULL; @@ -29,10 +70,18 @@ void Speedy::listen() server.listen(ip, [this](http::Request& req, http::Response& res) { auto url = req.url; - node *n = r3_tree_matchl(this->n, url.c_str(), url.size(), NULL); - if (n) { - auto callback = *reinterpret_cast<http::request_cb_t*>(n->data); - callback(req, res); + 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"); } diff --git a/speedy/test.cpp b/speedy/test.cpp index 43a21fd97..a0d07c2e8 100644 --- a/speedy/test.cpp +++ b/speedy/test.cpp @@ -2,33 +2,65 @@ #include "speedy.hpp" -// TODO: still doesn't work -// debug the whole thing -void test(http::request_cb_t callback, speedy::Speedy &app) { - app.get("/test", callback); +const char *test_url_1 = "/test1"; +const char *test_url_2 = "/test2"; +const char *test_url_3 = "/test3"; +const char *test_response = "test"; + +void test_get(const http::request_cb_t &&callback, speedy::Speedy &app) { + app.get(test_url_3, callback); } -auto foo = [](http::Request& req, http::Response& res) { - res.send("foo"); +void test_post(const http::request_cb_t &&callback, speedy::Speedy &app) { + app.post(test_url_3, callback); +} + +void test_put(const http::request_cb_t &&callback, speedy::Speedy &app) { + app.put(test_url_3, callback); +} + +void test_delete(const http::request_cb_t &&callback, speedy::Speedy &app) { + app.del(test_url_3, callback); +} + +auto test_callback = [](http::Request& req, http::Response& res) { + res.send(test_response); }; int main(void) { + // speedy init uv::UvLoop loop; http::Ipv4 ip("0.0.0.0", 3400); - speedy::Speedy app(loop, ip); - app.get("/foo", foo); - app.get("/bar", [](http::Request& req, http::Response& res) { - res.send("bar"); + + // GET methods + app.get(test_url_1, test_callback); + app.get(test_url_2, [](http::Request& req, http::Response& res) { + res.send(test_response); }); - auto cb = [](http::Request& req, http::Response& res) { - res.send("test"); - }; - test(http::request_cb_t(cb), app); + test_get(test_callback, app); + // POST examples + app.post(test_url_1, test_callback); + app.post(test_url_2, [](http::Request& req, http::Response& res) { + res.send(test_response); + }); + test_post(test_callback, app); + // PUT examples + app.put(test_url_1, test_callback); + app.put(test_url_2, [](http::Request& req, http::Response& res) { + res.send(test_response); + }); + test_put(test_callback, app); + // DELETE examples + app.del(test_url_1, test_callback); + app.del(test_url_2, [](http::Request& req, http::Response& res) { + res.send(test_response); + }); + test_delete(test_callback, app); + // app run app.listen(); - loop.run(uv::UvLoop::Mode::Default); return 0; diff --git a/speedy/test.py b/speedy/test.py new file mode 100644 index 000000000..961684567 --- /dev/null +++ b/speedy/test.py @@ -0,0 +1,22 @@ +import requests + +endpoint = 'http://localhost:3400/test%s' +methods = [('GET', requests.get), ('POST', requests.post), ('PUT', requests.put), ('DELETE', requests.delete)] + +print '' +isAllFine = True +for index in range(1, 4): + for name, method in methods: + url = endpoint % index + r = method(url) + if r.status_code == 200 and r.text == 'test': + print name, url, 'PASS' + else: + print name, url, 'FAIL' + isAllFine = False +print '' +if isAllFine: + print 'Great. All tests have passed :)' +else: + print 'Fuckup. Something went wrong!' +print ''