Add working tree
This commit is contained in:
10
Makefile
10
Makefile
@@ -1,8 +1,8 @@
|
||||
CC = g++
|
||||
CFLAGS = -Wall -Wextra -Werror
|
||||
CFILES = router.cpp path.cpp request.cpp response.cpp
|
||||
OFILES = router.o path.o request.o response.o
|
||||
HFILES = router.hpp path.hpp request.hpp response.hpp http.hpp
|
||||
CFLAGS = -Wall -Wextra -Werror
|
||||
CFILES = router.cpp path.cpp request.cpp response.cpp tree.cpp
|
||||
OFILES = router.o path.o request.o response.o tree.o
|
||||
HFILES = router.hpp path.hpp request.hpp response.hpp http.hpp tree.hpp
|
||||
|
||||
NAME = libhttpablu.a
|
||||
|
||||
@@ -12,7 +12,7 @@ $(NAME): ofiles
|
||||
ar rcs $(NAME) $(OFILES)
|
||||
|
||||
ofiles:
|
||||
g++ $(CFLAGS) -std=c++20 -O -c $(CFILES)
|
||||
g++ $(CFLAGS) -std=c++20 -g -O0 -c $(CFILES)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES)
|
||||
|
||||
89
main.cpp
89
main.cpp
@@ -1,5 +1,6 @@
|
||||
#include "http.hpp"
|
||||
#include "router.hpp"
|
||||
#include "tree.hpp"
|
||||
|
||||
using namespace http;
|
||||
|
||||
@@ -9,36 +10,70 @@ void HelloWorld(Request req, Response *res) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
Router router(8181);
|
||||
Tree t;
|
||||
|
||||
// Allow all Methods
|
||||
router.Handle("/helloWorld", HelloWorld);
|
||||
|
||||
router.Handle("/healthz", [](Request req, Response *res) {
|
||||
res->SetStatusCode(statuscode::OK);
|
||||
res->SetPayload(std::vector<std::byte>());
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
// Only allow GET
|
||||
router.Handle("GET /echo/{name}", [](Request req, Response *res) {
|
||||
std::string name = req.path.Get("name").value_or("No Name given");
|
||||
res->SetPayload("Hello " + name);
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
// Only allow POST
|
||||
router.Handle("POST /echo/{name}", [](Request req, Response *res) {
|
||||
std::string name = req.path.Get("name").value_or("No Name given");
|
||||
res->SetPayload("Hello with Post" + name);
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
router.Handle("/", [](Request req, Response *res) {
|
||||
t.AddPath("/test/dummy", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
router.Start();
|
||||
return 0;
|
||||
t.AddPath("/test/dummy/main", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
t.AddPath("/test/dummy/main2", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
t.AddPath("/test/dummy2/main", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
t.AddPath("/var/main", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
t.AddPath("/test/dummy2", [](Request req, Response *res) {
|
||||
res->SetPayload("Main");
|
||||
res->SetContentType("text/plain");
|
||||
});
|
||||
|
||||
t.DebugPrint();
|
||||
|
||||
// Router router(8181);
|
||||
//
|
||||
// // Allow all Methods
|
||||
// router.Handle("/helloWorld", HelloWorld);
|
||||
//
|
||||
// router.Handle("/healthz", [](Request req, Response *res) {
|
||||
// res->SetStatusCode(statuscode::OK);
|
||||
// res->SetPayload(std::vector<std::byte>());
|
||||
// res->SetContentType("text/plain");
|
||||
// });
|
||||
//
|
||||
// // Only allow GET
|
||||
// router.Handle("GET /echo/{name}", [](Request req, Response *res) {
|
||||
// std::string name = req.path.Get("name").value_or("No Name given");
|
||||
// res->SetPayload("Hello " + name);
|
||||
// res->SetContentType("text/plain");
|
||||
// });
|
||||
//
|
||||
// // Only allow POST
|
||||
// router.Handle("POST /echo/{name}", [](Request req, Response *res) {
|
||||
// std::string name = req.path.Get("name").value_or("No Name given");
|
||||
// res->SetPayload("Hello with Post" + name);
|
||||
// res->SetContentType("text/plain");
|
||||
// });
|
||||
//
|
||||
// router.Handle("/", [](Request req, Response *res) {
|
||||
// res->SetPayload("Main");
|
||||
// res->SetContentType("text/plain");
|
||||
// });
|
||||
//
|
||||
// router.Start();
|
||||
// return 0;
|
||||
}
|
||||
|
||||
116
tree.cpp
Normal file
116
tree.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "tree.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
using namespace http;
|
||||
|
||||
std::vector<std::string> split(std::string s, std::string delimiter) {
|
||||
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
|
||||
std::string token;
|
||||
std::vector<std::string> res;
|
||||
|
||||
while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
|
||||
token = s.substr(pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
if (token != "") {
|
||||
res.push_back(token);
|
||||
}
|
||||
}
|
||||
|
||||
token = s.substr(pos_start);
|
||||
if (token != "") {
|
||||
res.push_back(token);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Node::Node(std::string sub) {
|
||||
m_subPath = sub;
|
||||
m_isDummy = true;
|
||||
m_isValue = false;
|
||||
m_function = nullptr;
|
||||
}
|
||||
|
||||
Node::Node(std::string sub, bool isValue,
|
||||
std::function<void(Request, Response *)> func) {
|
||||
m_subPath = sub;
|
||||
m_isValue = isValue;
|
||||
m_function = func;
|
||||
m_isDummy = false;
|
||||
}
|
||||
|
||||
void create_dummy_nodes(std::shared_ptr<Node> **root,
|
||||
std::vector<std::string> rest) {
|
||||
auto curr = *root;
|
||||
for (auto next : rest) {
|
||||
auto dummy = std::make_shared<Node>(Node{next});
|
||||
(*curr)->m_next.insert_or_assign(next, dummy);
|
||||
curr = &dummy;
|
||||
}
|
||||
root = &curr;
|
||||
}
|
||||
|
||||
void addNode(std::shared_ptr<Node> const &parent, std::string path,
|
||||
std::vector<std::string> rest,
|
||||
std::function<void(Request, Response *)> func) {
|
||||
std::shared_ptr<Node> curr = parent->m_next[path];
|
||||
if (rest.size() == 0) {
|
||||
if (curr) {
|
||||
curr->m_isDummy = false;
|
||||
curr->m_function = func;
|
||||
} else {
|
||||
std::shared_ptr<Node> leaf =
|
||||
std::make_shared<Node>(Node{path, false, func});
|
||||
parent->m_next.insert_or_assign(path, leaf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (curr) {
|
||||
auto newPath = rest.front();
|
||||
// Ineffiecient, use deque
|
||||
rest.erase(rest.begin());
|
||||
addNode(curr, newPath, rest, func);
|
||||
} else {
|
||||
auto newPath = rest.front();
|
||||
rest.erase(rest.begin());
|
||||
std::shared_ptr<Node> leaf = std::make_shared<Node>(Node{path});
|
||||
parent->m_next.insert_or_assign(path, leaf);
|
||||
addNode(leaf, newPath, rest, func);
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::AddPath(std::string path,
|
||||
std::function<void(Request, Response *)> func) {
|
||||
auto subPaths = split(path, "/");
|
||||
|
||||
if (subPaths.size() == 0 && m_root == nullptr) {
|
||||
m_root = std::make_shared<Node>(Node{"", false, func});
|
||||
return;
|
||||
} else if (subPaths.size() == 0) {
|
||||
m_root->m_function = func;
|
||||
return;
|
||||
} else if (m_root == nullptr) {
|
||||
m_root = std::make_shared<Node>(Node{""});
|
||||
}
|
||||
|
||||
auto newPath = subPaths.front();
|
||||
subPaths.erase(subPaths.begin());
|
||||
addNode(m_root, newPath, subPaths, func);
|
||||
}
|
||||
|
||||
void printNode(std::shared_ptr<Node> node, size_t depth, size_t max_depth) {
|
||||
if (depth >= max_depth) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << std::string(depth, ' ') << "sub: \"" << node->m_subPath
|
||||
<< "\" IsDummy: " << node->m_isDummy << std::endl;
|
||||
for (auto &next : node->m_next) {
|
||||
printNode(next.second, depth + 1, max_depth);
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::DebugPrint() { printNode(m_root, 0, 10); }
|
||||
38
tree.hpp
Normal file
38
tree.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef TREE_H
|
||||
#define TREE_H
|
||||
|
||||
#include "request.hpp"
|
||||
#include "response.hpp"
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
namespace http {
|
||||
|
||||
class Node {
|
||||
public:
|
||||
bool m_isValue;
|
||||
bool m_isDummy;
|
||||
std::string m_subPath;
|
||||
std::map<std::string, std::shared_ptr<Node>> m_next;
|
||||
std::function<void(Request, Response *)> m_function;
|
||||
|
||||
public:
|
||||
Node(std::string subPath, bool isValue,
|
||||
std::function<void(Request, Response *)>);
|
||||
Node(std::string subPath);
|
||||
};
|
||||
|
||||
class Tree {
|
||||
private:
|
||||
std::shared_ptr<Node> m_root;
|
||||
std::string m_method;
|
||||
size_t depth;
|
||||
|
||||
public:
|
||||
void AddPath(std::string, std::function<void(Request, Response *)>);
|
||||
void DebugPrint();
|
||||
};
|
||||
} // namespace http
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user