From 925ff203a4c9ed1f2504f04da20f2a59b503cce5 Mon Sep 17 00:00:00 2001 From: Pablu23 Date: Mon, 8 Jul 2024 16:37:28 +0200 Subject: [PATCH] Add Method Routing and case insensitive routing patterns --- README.md | 10 +++++++++ main.cpp | 59 ++++++++--------------------------------------------- request.cpp | 1 + request.hpp | 1 + router.cpp | 22 +++++++++++++++----- 5 files changed, 37 insertions(+), 56 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..825b6cd --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Http Router which is supposed to be similar to the standard Golang Router +Todos: + - Routing to Tree instead of map + - Cmake maybe? + - Make redirects available + - Threading + - Stop + - React to Method + - Implement actual http protocol + - Post Form diff --git a/main.cpp b/main.cpp index 01c1060..c8e8f61 100644 --- a/main.cpp +++ b/main.cpp @@ -10,13 +10,20 @@ int main() { return res; }); - router.Handle("/echo/{name}", [](Request req, Response res) -> Response { + router.Handle("GET /echo/{name}", [](Request req, Response res) -> Response { std::string name = req.path.Get("name").value_or("No Name given"); res.SetPayload("Hello " + name); res.SetContentType("text/plain"); return res; }); + router.Handle("POST /echo/{name}", [](Request req, Response res) -> Response { + std::string name = req.path.Get("name").value_or("No Name given"); + res.SetPayload("Hello with Post" + name); + res.SetContentType("text/plain"); + return res; + }); + router.Handle("/", [](Request req, Response res) -> Response { res.SetPayload("Main"); res.SetContentType("text/plain"); @@ -26,53 +33,3 @@ int main() { router.Start(); return 0; } - -// void server() { -// int serverSocket = socket(AF_INET, SOCK_STREAM, 0); -// sockaddr_in serverAddress; -// serverAddress.sin_family = AF_INET; -// serverAddress.sin_port = htons(8080); -// serverAddress.sin_addr.s_addr = INADDR_ANY; -// -// int err = bind(serverSocket, (struct sockaddr *)&serverAddress, -// sizeof(serverAddress)); -// if (err != 0) { -// std::cout << "error binding " << strerror(errno) << std::endl; -// exit(1); -// } -// -// err = listen(serverSocket, 5); -// if (err != 0) { -// std::cout << "error listening " << strerror(errno) << std::endl; -// exit(1); -// } -// -// std::vector buffer(1024); -// while (true) { -// int clientSocket = accept(serverSocket, nullptr, nullptr); -// int read = recv(clientSocket, buffer.data(), buffer.size(), 0); -// buffer.resize(read); -// Request req(buffer); -// Response res = Response(http::statusCode::NOT_FOUND); -// if (req.HasData()) { -// auto data = req.Data(); -// res.SetPayload(data); -// } else { -// res.SetPayload("Hello world!"); -// } -// -// res.SetContentType("text/plain"); -// res.Send(clientSocket); -// close(clientSocket); -// } -// -// if (shutdown(serverSocket, SHUT_RDWR) < 0) { -// std::cout << "error shutdown " << strerror(errno) << std::endl; -// exit(1); -// } -// -// if (close(serverSocket) < 0) { -// std::cout << "error closing socket " << strerror(errno) << std::endl; -// exit(1); -// } -// } diff --git a/request.cpp b/request.cpp index 2effb5d..9f034ed 100644 --- a/request.cpp +++ b/request.cpp @@ -89,5 +89,6 @@ void Request::Print() { } } +std::string Request::Method() { return m_method; } bool Request::HasData() { return m_payload.size() != 0; } std::vector Request::Data() { return m_payload; } diff --git a/request.hpp b/request.hpp index c933e89..6258779 100644 --- a/request.hpp +++ b/request.hpp @@ -23,6 +23,7 @@ public: explicit Request(std::vector buf); void Print(); bool HasData(); + std::string Method(); std::vector Data(); }; #endif // !REQUEST_HEADER_H diff --git a/router.cpp b/router.cpp index f29ece2..2ce6d23 100644 --- a/router.cpp +++ b/router.cpp @@ -1,7 +1,10 @@ #include "router.hpp" +#include // std::equal +#include // std::tolower #include -#include #include +#include // std::string_view +#include #include #include @@ -41,11 +44,20 @@ void Router::Handle(std::string pathPattern, // Probably dont use map but a tree for it, then traverse tree for routing Response Router::Route(Request req) { for (const auto &[key, value] : m_routes) { - int pos = 0; - std::string path = req.path.Base(); std::string pattern = key; - std::string patternCopy = key; + + int mPos = pattern.find(' '); + std::string method = pattern.substr(0, mPos); + + if (mPos != -1 && method != req.Method()) { + continue; + } + + pattern.erase(0, mPos + 1); + std::string patternCopy = pattern; + std::string path = req.path.Base(); bool found = false; + int pos = 0; while (pos != -1) { found = true; pos = pattern.find('/'); @@ -54,7 +66,7 @@ Response Router::Route(Request req) { int uPos = path.find('/'); std::string u = path.substr(0, uPos); - if (!p.starts_with('{') && p != u) { + if (!p.starts_with('{') && strcasecmp(p.data(), u.data()) != 0) { found = false; break; }