Deleted src/api - this is the old HTTP

This commit is contained in:
Florijan Stamenkovic 2017-02-02 15:53:34 +01:00
parent 46dbc08d4e
commit 029a3ff09b
12 changed files with 0 additions and 795 deletions

View File

@ -1,21 +0,0 @@
CXX=clang++
CFLAGS=-std=c++11 -Wall -O2
LDFLAGS=-luv -lhttp_parser ../speedy/r3/.libs/libr3.a -L/usr/local/lib -lpcre
# debug only
INC=-I../
SOURCES=$(wildcard *.cpp)
EXECUTABLE=test.out
# OBJECTS=$(SOURCES:.cpp=.o)
all: $(EXECUTABLE)
$(EXECUTABLE): $(SOURCES)
$(CXX) $(CFLAGS) $(SOURCES) -o $(EXECUTABLE) $(INC) $(LDFLAGS)
# .cpp.o:
# $(CXX) $(CFLAGS) $< -o $@ $(LDFLAGS) $(INC)
.PHONY:
clean:
rm -f *.out
rm -f *.o

View File

@ -1,86 +0,0 @@
# this script generates the include.hpp file for restful resources
import re
import os
from itertools import chain
print "generating include.hpp file"
resource_path = 'resources'
template_path = 'resources/include.hpp.template'
include_path = 'resources/include.hpp'
# remove the old version of the file if exists
if os.path.isfile(include_path):
os.remove(include_path)
class Resource(object):
""" represents a restful resource class for speedy """
def __init__(self, filename, class_name, url):
self.filename = filename
self.class_name = class_name
self.url = url
def scan_resources(filename):
with open(os.path.join(resource_path, filename)) as f:
url_regex = re.compile('#pragma\s+url\s+([^\s]+)\s+')
class_name_regex = re.compile('\s*class\s*(\w+)\s*\:')
lines = f.readlines()
pairs = zip(lines, lines[1:])
for first, second in pairs:
url = re.search(url_regex, first)
if url is None:
continue
class_name = re.search(class_name_regex, second)
if class_name is None:
continue
yield Resource(filename, class_name.group(1), url.group(1))
def load_resources():
resources = chain(*[scan_resources(f) for f in os.listdir(resource_path)
if f.endswith('.hpp')])
return [r for r in resources if r.class_name is not None]
def write_includes(file, resources):
for filename in [resource.filename for resource in resources]:
print 'writing include for', filename
file.write('#include "{}"\n'.format(filename))
def write_inits(file, resources):
for class_name, url in [(r.class_name, r.url) for r in resources]:
print('writing init for {} -> {}'.format(class_name, url))
file.write(' insert<{}>(container, "{}");\n'
.format(class_name, url))
def make_include_file():
resources = load_resources()
with open(template_path, 'r') as ftemplate:
with open(include_path, 'w') as finclude:
for line in ftemplate:
if '<INCLUDE>' in line:
write_includes(finclude, resources)
continue
if '<INIT>' in line:
write_inits(finclude, resources)
continue
finclude.write(line)
if __name__ == '__main__':
make_include_file()

View File

@ -1 +0,0 @@
include.hpp

View File

@ -1,150 +0,0 @@
#pragma once
#include <unordered_map>
#include "api/restful/resource.hpp"
#include "query_engine/query_stripper.hpp"
#include "query_engine/query_stripped.hpp"
#include "database/db.hpp"
#include "utils/hashing/fnv.hpp"
#include "threading/task.hpp"
#include "storage/model/properties/all.hpp"
std::vector<std::string> queries {
"CREATE (n:Item{id:1}) RETURN n",
"MATCH (n:Item{id:1}),(m:Item{id:1}) CREATE (n)-[r:test]->(m) RETURN r",
"MATCH (n:Item{id:1}) SET n.prop = 7 RETURN n",
"MATCH (n:Item{id:1}) RETURN n",
"MATCH (n:Item{id:1})-[r]->(m) RETURN count(r)"
};
#pragma url /transaction/commit
class Demo : public Resource<Demo, POST>
{
public:
QueryStripper<int, int, int, int> stripper;
std::map<uint64_t, std::function<std::string(const code_args_t&)>> query_f;
Demo(Task::sptr task, Db::sptr db) :
Resource(task, db),
stripper(make_query_stripper(TK_INT, TK_FLOAT, TK_STR, TK_BOOL))
{
std::vector<uint64_t> hashes;
for(auto& query : queries)
{
auto strip = stripper.strip(query);
auto hash = fnv(strip.query);
hashes.push_back(hash);
}
query_f[hashes[0]] = [db](const code_args_t& args) {
auto& t = db->tx_engine.begin();
auto v = db->graph.vertices.insert(t);
v.property("id", args[0]);
t.commit();
return std::to_string(v.property("id").as<Int32>().value);
};
query_f[hashes[1]] = [db](const code_args_t& args) {
return std::string("ALO");
auto& t = db->tx_engine.begin();
auto v1 = db->graph.vertices.find(t, args[0]->as<Int32>().value);
if(!v1)
return t.commit(), std::string("not found");
auto v2 = db->graph.vertices.find(t, args[1]->as<Int32>().value);
if(!v2)
return t.commit(), std::string("not found");
auto e = db->graph.edges.insert(t);
v1.vlist->update(t)->data.out.add(e.vlist);
v2.vlist->update(t)->data.in.add(e.vlist);
e.from(v1.vlist);
e.to(v2.vlist);
e.edge_type(EdgeType("test"));
t.commit();
return e.edge_type();
};
query_f[hashes[2]] = [db](const code_args_t& args) {
auto& t = db->tx_engine.begin();
auto id = args[0]->as<Int32>();
auto v = db->graph.vertices.find(t, id.value);
if (!v)
return t.commit(), std::string("not found");
v.property("prop", args[1]);
t.commit();
return std::to_string(v.property("id").as<Int32>().value);
};
query_f[hashes[3]] = [db](const code_args_t& args) {
auto& t = db->tx_engine.begin();
auto id = args[0]->as<Int32>();
auto v = db->graph.vertices.find(t, id.value);
t.commit();
if(!v)
return std::string("not found");
return std::to_string(v.property("id").as<Int32>().value);
};
query_f[hashes[4]] = [db](const code_args_t& args) {
auto& t = db->tx_engine.begin();
auto id = args[0]->as<Int32>();
auto v = db->graph.vertices.find(t, id.value);
t.commit();
if(!v)
return std::string("not found");
return std::to_string(v.out_degree());
};
}
int x{0};
void post(sp::Request& req, sp::Response& res)
{
task->run([this, &req]() {
auto query = req.json["statements"][0]["statement"].GetString();
auto strip = stripper.strip(query);
auto hash = fnv(strip.query);
auto it = query_f.find(hash);
if(it == query_f.end())
{
std::cout << "Unrecognized query '"
<< query << "' with hash "
<< hash << "." << std::endl;
return std::string("Unrecognized Query");
}
return it->second(strip.arguments);
},
[&req, &res](std::string str) {
return res.send(http::Status::Ok, str);
});
}
};

View File

@ -1,48 +0,0 @@
/** @file include.hpp
* @brief Links all restful resources to the application
*
* This file is autogenerated by the python script link_resources.py
*
* YOU SHOULD NOT EDIT THIS FILE MANUALLY!
*
* well, only if you're editing the template file, that's ok :)
*/
#pragma once
#include <list>
#include <memory>
#include "utils/ioc/container.hpp"
#include "api/restful/resource.hpp"
#include "transactions/engine.hpp"
#include "threading/task.hpp"
#include "speedy/speedy.hpp"
// for each file in this folder a script will generate an include directive if
// this file contains any resources
// e.g.
// #include "node.hpp"
// #include "relationship.hpp"
<INCLUDE>
template <class T>
void insert(ioc::Container& container, const std::string& path)
{
auto app = container.resolve<sp::Speedy>();
auto resource = container.singleton<T, Task, Db>();
resource->link(*app, path);
}
void init(ioc::Container& container)
{
// for each resource in a file included above, the script will generate a
// linkage command call to the function above
// e.g.
// insert<CLASS>(PATH);
//
// insert<Nodes>("/node");
// insert<Node>("/node/{id:\\d+}");
<INIT>
}

View File

@ -1,155 +0,0 @@
#pragma once
#include <random>
#include "debug/log.hpp"
#include "mvcc/version_list.hpp"
#include "api/response_json.hpp"
#include "api/restful/resource.hpp"
#include "storage/model/properties/property.hpp"
#pragma url /node
class Nodes : public Resource<Nodes, POST>
{
public:
using Resource::Resource;
void post(sp::Request& req, sp::Response& res)
{
task->run([this, &req]() {
// create transaction
auto& transaction = db->tx_engine.begin();
// insert a new vertex
auto vertex_accessor = db->graph.vertices.insert(transaction);
auto begin_it = req.json.MemberBegin();
auto end_it = req.json.MemberEnd();
for(auto it = begin_it; it != end_it; ++it)
{
vertex_accessor.template property<String>(
it->name.GetString(), it->value.GetString()
);
}
// commit the transaction
transaction.commit();
return std::move(vertex_accessor);
},
[&req, &res](VertexAccessor&& vertex_accessor) {
return res.send(
http::Status::Created,
vertex_create_response(vertex_accessor)
);
});
}
};
#pragma url /node/{id:\\d+}
class Node : public Resource<Node, GET, PUT, DELETE>
{
public:
using Resource::Resource;
void get(sp::Request& req, sp::Response& res)
{
task->run([this, &req]() {
// create transaction
auto& transaction = db->tx_engine.begin();
// read id param
Id id(std::stoull(req.params[0]));
// find node
auto vertex_accessor = db->graph.vertices.find(transaction, id);
// commit the transaction
transaction.commit();
return std::move(vertex_accessor);
},
[&req, &res](VertexAccessor&& vertex_accessor) {
if (vertex_accessor.empty()) {
return res.send(
http::Status::NotFound,
"The node was not found"
);
}
return res.send(
vertex_create_response(vertex_accessor)
);
});
}
void put(sp::Request& req, sp::Response& res)
{
task->run([this, &req]() {
// create transaction
auto& transaction = db->tx_engine.begin();
// read id param
Id id(std::stoull(req.params[0]));
// find node
auto vertex_accessor = db->graph.vertices.find(transaction, id);
if (vertex_accessor.empty())
return std::move(vertex_accessor);
auto begin_it = req.json.MemberBegin();
auto end_it = req.json.MemberEnd();
for(auto it = begin_it; it != end_it; ++it)
{
vertex_accessor.template property<String>(
it->name.GetString(), it->value.GetString()
);
}
// commit the transaction
transaction.commit();
return std::move(vertex_accessor);
},
[&req, &res](VertexAccessor&& vertex_accessor) {
if (vertex_accessor.empty()) {
return res.send(
http::Status::NotFound,
"The node was not found"
);
}
return res.send(vertex_create_response(vertex_accessor));
});
}
void del(sp::Request& req, sp::Response& res)
{
task->run([this, &req]() -> bool {
// create transaction
auto& transaction = db->tx_engine.begin();
// read id param
Id id(std::stoull(req.params[0]));
auto vertex_accessor = db->graph.vertices.find(transaction, id);
if (vertex_accessor.empty())
return false;
auto is_deleted = vertex_accessor.remove(transaction);
// commit the transaction
transaction.commit();
return is_deleted;
},
// pass something smarter
// e.g. enum { NotFound, Deleted, DeletionFaild }
[&req, &res](bool is_deleted) {
if (is_deleted)
return res.send(http::Status::Ok, "The node was deleted");
return res.send(http::Status::NotFound, "The node was not found");
});
}
};

View File

@ -1,15 +0,0 @@
#pragma once
#include "api/restful/resource.hpp"
#pragma url /ping
class Ping : public Resource<Ping, GET>
{
public:
using Resource::Resource;
void get(sp::Request& req, sp::Response& res)
{
return res.send(http::Status::NoContent, "");
}
};

View File

@ -1,38 +0,0 @@
#pragma once
#include "api/restful/resource.hpp"
#pragma url /relationship
class Relationships : public Resource<Relationships, POST>
{
public:
using Resource::Resource;
void post(sp::Request& req, sp::Response& res)
{
return res.send("POST /db/data/relationship");
}
};
#pragma url /relationship/{id:\\d+}
class Relationship : public Resource<Relationship, GET>
{
public:
using Resource::Resource;
void get(sp::Request& req, sp::Response& res)
{
return res.send("GET /db/data/relationship");
}
void put(sp::Request& req, sp::Response& res)
{
return res.send("PUT /db/data/relationship");
}
void del(sp::Request& req, sp::Response& res)
{
return res.send("DELETE /db/data/relationship");
}
};

View File

@ -1,56 +0,0 @@
#pragma once
#include "storage/vertex.hpp"
#include "storage/vertex_accessor.hpp"
#include "storage/writer/rapidjson_stringwriter.hpp"
StringBuffer vertex_props_to_buffer(const Vertex* vertex)
{
// make a string buffer
StringBuffer buffer;
JsonWriter<StringBuffer> writer(buffer);
// dump properties in this buffer
vertex->data.props.accept(writer);
writer.finish();
// respond to the use with the buffer
return buffer;
}
std::string vertex_props_to_string(const Vertex* vertex)
{
auto buffer = vertex_props_to_buffer(vertex);
return std::move(buffer.str());
}
// TODO: clear up naming
using RJStringBuffer = rapidjson::StringBuffer;
using RJStringWriter = rapidjson::Writer<RJStringBuffer>;
using ptr_RJStringWriter = std::shared_ptr<RJStringWriter>;
std::string vertex_create_response(const VertexAccessor& vertex_accessor)
{
// make a string buffer
RJStringBuffer buffer;
ptr_RJStringWriter writer = std::make_shared<RJStringWriter>(buffer);
writer->StartObject();
writer->String("metadata");
writer->StartObject();
writer->String("id");
writer->Int64(vertex_accessor.id());
writer->EndObject();
writer->String("data");
writer->StartObject();
// RapidJsonStringWriter dataBuffer(writer);
// auto properties = vertex_accessor.properties();
// properties.accept(dataBuffer);
writer->EndObject();
writer->EndObject();
return std::move(buffer.GetString());
}

View File

@ -1,50 +0,0 @@
#pragma once
#include "api/restful/restful_resource.hpp"
#include "database/db.hpp"
#include "threading/task.hpp"
#include "speedy/speedy.hpp"
template <class T, class... Ms>
class Resource
{
public:
/** @brief Resource constructor
*
* List ALL the dependencies here so that ioc can resolve them and store
* them to protected members so that derived resources can access them
*
* @param task shared_ptr to the task dispatching library
* @param db shared_ptr to the database instance
*/
Resource(Task::sptr task, Db::sptr db)
: task(task), db(db) {}
/** @brief Link all resources to an instance of speedy
*
* link_resources.py generates an include.hpp file which includes and
* instantinates all available resources. The include.hpp file also calls
* this method to link the resources to speedy for a given path
*/
void link(sp::Speedy& app, const std::string& path)
{
// make sure this is called once even if someone actually calls this
// function multiple times
std::call_once(once_flag, [this, &app, &path]() {
Restful<T, Ms...>(static_cast<T&>(*this), app, path);
});
}
protected:
// all resources have pointers to these instances add everything else
// neccessary here as a shared_ptr and also include it in the constructor
// and modify the include.hpp.template to include the new dependencies for
// resource linking
Task::sptr task;
Db::sptr db;
private:
std::once_flag once_flag;
};

View File

@ -1,156 +0,0 @@
#pragma once
#include <memory>
#include "speedy/speedy.hpp"
#include "utils/crtp.hpp"
#include "storage/model/properties/traversers/jsonwriter.hpp"
/** @brief GET handler method for the resource
* Contains the code for registering GET handler for a URL to Speedy
*/
struct GET
{
/** @brief Links ::get handler to speedy for a given path
*
* @tparam T Class type containing the required handler
* @param app Instance of speedy to register the method to
* @param path URL of the resource being registered
* @param resource Object containing ::get http::request_cb_t handler
*/
template <class T>
void link(sp::Speedy& app, const std::string& path, T& resource)
{
using namespace std::placeholders;
app.get(path, std::bind(&T::get, std::ref(resource), _1, _2));
}
};
/** @brief POST handler method for the resource
* Contains the code for registering POST handler for a URL to Speedy
*/
struct POST
{
/** @brief Links ::post handler to speedy for a given path
*
* @tparam T Class type containing the required handler
* @param app Instance of speedy to register the method to
* @param path URL of the resource being registered
* @param resource Object containing ::post http::request_cb_t handler
*/
template <class T>
void link(sp::Speedy& app, const std::string& path, T& resource)
{
using namespace std::placeholders;
app.post(path, std::bind(&T::post, std::ref(resource), _1, _2));
}
};
struct PUT
{
template <class T>
void link(sp::Speedy& app, const std::string& path, T& resource)
{
using namespace std::placeholders;
app.put(path, std::bind(&T::put, std::ref(resource), _1, _2));
}
};
struct DELETE
{
template <class T>
void link(sp::Speedy& app, const std::string& path, T& resource)
{
using namespace std::placeholders;
app.del(path, std::bind(&T::del, std::ref(resource), _1, _2));
}
};
namespace detail
{
/** @brief Registers a method for a path to speedy
*
* @tparam T Derived class containing the handler of the method
* @tparam M A method to register
*/
template <class T, class M>
struct Method : public M
{
/** Registers a route handler for the resource
*
* Registers a method handler for M on the given URL
*
* @param app instance of speedy to register the method to
* @param path URL of the resource being registered
*/
Method(T& resource, sp::Speedy& app, const std::string& path)
{
M::link(app, path, resource);
}
};
/** @brief Generates the Method<T, M> inheritance for each M in Ms
*
* Implemented inheriting recursively using variadic templates
*
* @tparam T Derived class containing handlers for each method M in Ms
* @tparam Ms... Methods to register
*/
template <class T, class... Ms>
struct Methods;
/** @brief specialization of the struct Methods<T, Ms...>
*
* Unrolls one method M and generates a handler for this method by inheriting
* from Method<T, M> and generates the rest of the handlers recursively by
* inheriting from Methods<T, Ms...> and unrolling one M each time.
*
* @tparam T Derived class containing handlers for each method M in Ms
* @tparam M Unrolled method M for which to generate a handler
* @tparam Ms... The rest of the methods
*/
template <class T, class M, class... Ms>
struct Methods<T, M, Ms...> : public Method<T, M>, public Methods<T, Ms...>
{
Methods(T& resource, sp::Speedy& app, const std::string& path)
: Method<T, M>(resource, app, path),
Methods<T, Ms...>(resource, app, path) {}
};
/** @brief specialization of the struct Methods<T, Ms...>
*
* Specializes the recursion termination case containing only one method M
*
* @tparam T Derived class containing handlers for method M
* @tparam M Unrolled method M for which to generate a handler
*/
template <class T, class M>
struct Methods<T, M> : public Method<T, M>
{
using Method<T, M>::Method;
};
}
/** @brief Represents a restful resource
*
* Automatically registers get, put, post, del... methods inside the derived
* class T. Methods are given as a template parameter to the class. Valid
* template parameters are classes which implement a function
*
* void link(sp::Speedy&, const std::string&, T& resource)
*
* which registers a method you want to use with speedy
*
* @tparam T Derived class (CRTP)
* @tparam Ms... HTTP methods to register for this resource (GET, POST...)
*/
template <class T, class... Ms>
class Restful : public detail::Methods<T, Ms...>
{
public:
Restful(T& resource, sp::Speedy& app, const std::string& path)
: detail::Methods<T, Ms...>(resource, app, path) {}
};

View File

@ -1,19 +0,0 @@
#include <iostream>
#include "speedy/speedy.hpp"
#include "resources/include.hpp"
int main(void)
{
uv::UvLoop loop;
speedy::Speedy app(loop);
init(app);
http::Ipv4 ip("0.0.0.0", 3400);
app.listen(ip);
loop.run(uv::UvLoop::Mode::Default);
return 0;
}