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 ''