Add Method Routing and case insensitive routing patterns
This commit is contained in:
10
README.md
Normal file
10
README.md
Normal file
@@ -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
|
||||||
59
main.cpp
59
main.cpp
@@ -10,13 +10,20 @@ int main() {
|
|||||||
return res;
|
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");
|
std::string name = req.path.Get("name").value_or("No Name given");
|
||||||
res.SetPayload("Hello " + name);
|
res.SetPayload("Hello " + name);
|
||||||
res.SetContentType("text/plain");
|
res.SetContentType("text/plain");
|
||||||
return res;
|
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 {
|
router.Handle("/", [](Request req, Response res) -> Response {
|
||||||
res.SetPayload("Main");
|
res.SetPayload("Main");
|
||||||
res.SetContentType("text/plain");
|
res.SetContentType("text/plain");
|
||||||
@@ -26,53 +33,3 @@ int main() {
|
|||||||
router.Start();
|
router.Start();
|
||||||
return 0;
|
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<std::byte> 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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -89,5 +89,6 @@ void Request::Print() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Request::Method() { return m_method; }
|
||||||
bool Request::HasData() { return m_payload.size() != 0; }
|
bool Request::HasData() { return m_payload.size() != 0; }
|
||||||
std::vector<std::byte> Request::Data() { return m_payload; }
|
std::vector<std::byte> Request::Data() { return m_payload; }
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
explicit Request(std::vector<std::byte> buf);
|
explicit Request(std::vector<std::byte> buf);
|
||||||
void Print();
|
void Print();
|
||||||
bool HasData();
|
bool HasData();
|
||||||
|
std::string Method();
|
||||||
std::vector<std::byte> Data();
|
std::vector<std::byte> Data();
|
||||||
};
|
};
|
||||||
#endif // !REQUEST_HEADER_H
|
#endif // !REQUEST_HEADER_H
|
||||||
|
|||||||
22
router.cpp
22
router.cpp
@@ -1,7 +1,10 @@
|
|||||||
#include "router.hpp"
|
#include "router.hpp"
|
||||||
|
#include <algorithm> // std::equal
|
||||||
|
#include <cctype> // std::tolower
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <iostream>
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <string_view> // std::string_view
|
||||||
|
#include <strings.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -41,11 +44,20 @@ void Router::Handle(std::string pathPattern,
|
|||||||
// Probably dont use map but a tree for it, then traverse tree for routing
|
// Probably dont use map but a tree for it, then traverse tree for routing
|
||||||
Response Router::Route(Request req) {
|
Response Router::Route(Request req) {
|
||||||
for (const auto &[key, value] : m_routes) {
|
for (const auto &[key, value] : m_routes) {
|
||||||
int pos = 0;
|
|
||||||
std::string path = req.path.Base();
|
|
||||||
std::string pattern = key;
|
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;
|
bool found = false;
|
||||||
|
int pos = 0;
|
||||||
while (pos != -1) {
|
while (pos != -1) {
|
||||||
found = true;
|
found = true;
|
||||||
pos = pattern.find('/');
|
pos = pattern.find('/');
|
||||||
@@ -54,7 +66,7 @@ Response Router::Route(Request req) {
|
|||||||
int uPos = path.find('/');
|
int uPos = path.find('/');
|
||||||
std::string u = path.substr(0, uPos);
|
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;
|
found = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user