Stuff
This commit is contained in:
parent
792abbee93
commit
638276d8e0
12 changed files with 299 additions and 27 deletions
121
Source/InbuildMiddleWare.cpp
Normal file
121
Source/InbuildMiddleWare.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "StringUtils.h"
|
||||
#include "VWeb.h"
|
||||
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
||||
namespace VWeb {
|
||||
#pragma region AUTH
|
||||
PreMiddleWareReturn AuthWare::PreHandle(Request &request) {
|
||||
if (m_AuthFunction)
|
||||
return m_AuthFunction(request);
|
||||
return {};
|
||||
}
|
||||
|
||||
#pragma endregion AUTH
|
||||
|
||||
#pragma region SESSION
|
||||
|
||||
static std::string GenerateSID() {
|
||||
static std::random_device dev;
|
||||
static std::mt19937 rng(dev());
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, 15);
|
||||
|
||||
const char *v = "0123456789abcdef";
|
||||
const bool dashArray[] = {false, false, false, false, true, false,
|
||||
true, false, true, false, true, false,
|
||||
false, false, false, false};
|
||||
|
||||
std::stringstream res;
|
||||
for (bool dash : dashArray) {
|
||||
if (dash)
|
||||
res << "-";
|
||||
res << v[dist(rng)];
|
||||
res << v[dist(rng)];
|
||||
}
|
||||
return res.str();
|
||||
}
|
||||
|
||||
SessionManager::SessionManager() {
|
||||
m_GCThread = CreateRef<std::thread>([this]() {
|
||||
while (m_IsRunning) {
|
||||
if (m_Counter == 59) {
|
||||
GC();
|
||||
m_Counter = -1;
|
||||
}
|
||||
m_Counter++;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
});
|
||||
}
|
||||
SessionManager::~SessionManager() {
|
||||
m_IsRunning = false;
|
||||
m_GCThread->join();
|
||||
}
|
||||
|
||||
PreMiddleWareReturn SessionManager::PreHandle(Request &request) {
|
||||
auto &cookies = request.CookieData;
|
||||
if (!cookies->Has("sid"))
|
||||
return {};
|
||||
auto &cookie = cookies->Get("sid");
|
||||
std::lock_guard<std::mutex> lck(m_Mutex);
|
||||
if (!m_Sessions.contains(cookie.Value))
|
||||
return {};
|
||||
auto &session = m_Sessions[cookie.Value];
|
||||
session->Update();
|
||||
request.SessionData = session;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool SessionManager::PostHandle(const Request &request, Response &response) {
|
||||
if (response.SessionData->Id.empty() &&
|
||||
response.SessionData->ContainsData()) {
|
||||
response.SessionData->Update();
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(m_Mutex);
|
||||
response.SessionData->Id = GenerateSID();
|
||||
while (m_Sessions.contains(response.SessionData->Id))
|
||||
response.SessionData->Id = GenerateSID();
|
||||
}
|
||||
m_Sessions[response.SessionData->Id] = response.SessionData;
|
||||
auto &sidCookie = response.CookieData->Get("sid");
|
||||
sidCookie.HttpOnly = true;
|
||||
sidCookie.Secure = true;
|
||||
sidCookie.Value = response.SessionData->Id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionManager::GC() {
|
||||
std::lock_guard<std::mutex> lck(m_Mutex);
|
||||
std::vector<std::string_view> mark_as_delete;
|
||||
for (auto &itemToCollect : m_Sessions) {
|
||||
if (!itemToCollect.second->IsValid())
|
||||
mark_as_delete.push_back(itemToCollect.first);
|
||||
}
|
||||
|
||||
for (auto &i : mark_as_delete)
|
||||
m_Sessions.erase(i.data());
|
||||
}
|
||||
#pragma endregion SESSION
|
||||
#pragma region COOKIES
|
||||
PreMiddleWareReturn CookieManager::PreHandle(Request &request) {
|
||||
auto &cookieHeaders = request.Header("Cookie");
|
||||
auto &cookies = request.CookieData;
|
||||
if (cookieHeaders.Size() > 0) {
|
||||
auto &values = cookieHeaders.Values();
|
||||
for (auto &rawCookie : cookieHeaders.Values()) {
|
||||
auto splitCookies = String::Split(rawCookie, ";");
|
||||
for (auto &cookie : splitCookies) {
|
||||
auto split = String::Split(cookie, "=");
|
||||
String::Trim(split[0]);
|
||||
String::Trim(split[1]);
|
||||
cookies->CreateOld(split[0], split[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
#pragma endregion COOKIES
|
||||
} // namespace VWeb
|
||||
|
|
@ -1,15 +1,21 @@
|
|||
#include <VWeb.h>
|
||||
|
||||
namespace VWeb {
|
||||
void MiddleWareHandler::HandlePre(Ref<Request> &request) {
|
||||
std::optional<Ref<Response>>
|
||||
MiddleWareHandler::HandlePre(Ref<Request> &request) {
|
||||
for (auto &[key, middleWare] : m_MiddleWares) {
|
||||
middleWare->PreHandle(*request);
|
||||
auto data = middleWare->PreHandle(*request);
|
||||
if (data.has_value())
|
||||
return data;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
void MiddleWareHandler::HandlePost(Ref<Request> &request,
|
||||
Ref<Response> &response) {
|
||||
for (auto &[key, middleWare] : m_MiddleWares) {
|
||||
middleWare->PostHandle(*request, *response);
|
||||
if (!middleWare->PostHandle(*request, *response)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void MiddleWareHandler::Shutdown(Ref<Request> &request,
|
||||
|
|
|
|||
|
|
@ -55,8 +55,15 @@ struct RequestJob : public WorkerJob {
|
|||
}
|
||||
MRequest->CookieData = CreateRef<Cookies>();
|
||||
MRequest->SessionData = CreateRef<Session>();
|
||||
MMiddleWareHandler->HandlePre(MRequest);
|
||||
auto response = MRouter->HandleRoute(MRequest);
|
||||
Ref<Response> response;
|
||||
auto preValue = MMiddleWareHandler->HandlePre(MRequest);
|
||||
if (preValue.has_value()) {
|
||||
response = preValue.value();
|
||||
response->SessionData = MRequest->SessionData;
|
||||
response->CookieData = MRequest->CookieData;
|
||||
} else {
|
||||
response = MRouter->HandleRoute(MRequest);
|
||||
}
|
||||
MMiddleWareHandler->HandlePost(MRequest, response);
|
||||
auto content = response->GetResponse();
|
||||
MRequestHandler->AddSendResponse(
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ static std::unordered_map<HttpStatusCode, std::string> s_HTTPCodeToString = {
|
|||
{HttpStatusCode::NetworkAuthenticationRequired,"511 Network Authentication Required"}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
Ref<Response> Response::FromCode(HttpStatusCode code) {
|
||||
auto response = CreateRef<Response>();
|
||||
response->SetStatus(code);
|
||||
return response;
|
||||
}
|
||||
|
||||
std::string Response::GetResponse() {
|
||||
std::string content = m_Content.str();
|
||||
auto headData = TransformHeaders(content);
|
||||
|
|
|
|||
|
|
@ -80,4 +80,8 @@ bool Route::SupportsMethod(const Request &request) {
|
|||
std::find(m_AllowedMethods.begin(), m_AllowedMethods.end(),
|
||||
request.Method) != m_AllowedMethods.end();
|
||||
}
|
||||
void Route::AllowMethod(HttpMethod method) {
|
||||
if (std::find(m_AllowedMethods.begin(), m_AllowedMethods.end(), method) == m_AllowedMethods.end())
|
||||
m_AllowedMethods.push_back(method);
|
||||
}
|
||||
} // namespace VWeb
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <VWeb.h>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace VWeb {
|
||||
|
||||
|
|
@ -20,6 +21,33 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class InstanceHandleRoute : public Route {
|
||||
public:
|
||||
bool Get(const Request &request, Response &response) override {
|
||||
return GetFunc && GetFunc(request, response);
|
||||
}
|
||||
bool Post(const Request &request, Response &response) override {
|
||||
return PostFunc && PostFunc(request, response);
|
||||
}
|
||||
bool Put(const Request &request, Response &response) override {
|
||||
return PutFunc && PutFunc(request, response);
|
||||
}
|
||||
bool Patch(const Request &request, Response &response) override {
|
||||
return PatchFunc && PatchFunc(request, response);
|
||||
}
|
||||
bool Delete(const Request &request, Response &response) override {
|
||||
return DeleteFunc && DeleteFunc(request, response);
|
||||
}
|
||||
|
||||
protected:
|
||||
RouteFunction GetFunc{nullptr};
|
||||
RouteFunction PostFunc{nullptr};
|
||||
RouteFunction PutFunc{nullptr};
|
||||
RouteFunction PatchFunc{nullptr};
|
||||
RouteFunction DeleteFunc{nullptr};
|
||||
friend Router;
|
||||
};
|
||||
|
||||
Router::Router() { m_Routes["@"] = CreateRef<ErrorRoute>(); }
|
||||
|
||||
void Router::AddRoute(const std::string &name, const Ref<Route> &route) {
|
||||
|
|
@ -38,6 +66,7 @@ Ref<Response> Router::HandleRoute(Ref<Request> &request) {
|
|||
auto response = CreateRef<Response>();
|
||||
auto route = FindRoute(request);
|
||||
response->CookieData = request->CookieData;
|
||||
response->SessionData = request->SessionData;
|
||||
response->Method = request->Method;
|
||||
if (!route) {
|
||||
response->SetStatus(HttpStatusCode::NotFound);
|
||||
|
|
@ -94,4 +123,38 @@ void Router::AddToArgs(Ref<Request> &request, Vector<std::string> &items) {
|
|||
request->URLParameters.push_back(items[items.size() - 1]);
|
||||
items.pop_back();
|
||||
}
|
||||
|
||||
InstanceHandleRoute* GetOrNull(const std::string& path, Router* router) {
|
||||
InstanceHandleRoute* route;
|
||||
if (!router->m_Routes.contains(path)) {
|
||||
router->AddRoute(path, CreateRef<InstanceHandleRoute>());
|
||||
}
|
||||
route = dynamic_cast<InstanceHandleRoute*>(router->m_Routes[path].get());
|
||||
return route;
|
||||
}
|
||||
void Router::Get(const std::string &path, RouteFunction func) {
|
||||
auto* route = GetOrNull(path, this);
|
||||
if (route)
|
||||
route->GetFunc = std::move(func);
|
||||
}
|
||||
void Router::Post(const std::string &path, RouteFunction func) {
|
||||
auto* route = GetOrNull(path, this);
|
||||
if (route)
|
||||
route->PostFunc = std::move(func);
|
||||
}
|
||||
void Router::Put(const std::string &path, RouteFunction func) {
|
||||
auto* route = GetOrNull(path, this);
|
||||
if (route)
|
||||
route->PutFunc = std::move(func);
|
||||
}
|
||||
void Router::Patch(const std::string &path, RouteFunction func) {
|
||||
auto* route = GetOrNull(path, this);
|
||||
if (route)
|
||||
route->PatchFunc = std::move(func);
|
||||
}
|
||||
void Router::Delete(const std::string &path, RouteFunction func) {
|
||||
auto* route = GetOrNull(path, this);
|
||||
if (route)
|
||||
route->DeleteFunc = std::move(func);
|
||||
}
|
||||
} // namespace VWeb
|
||||
|
|
@ -8,6 +8,10 @@ Server::Server() {
|
|||
m_ServerConfig->EPoll = CreateRef<EPollManager>();
|
||||
m_ServerConfig->Socket = CreateRef<SocketManager>(m_ServerConfig);
|
||||
m_RequestHandler = CreateRef<RequestHandler>(m_ServerConfig->Socket);
|
||||
auto& middleWare = m_RequestHandler->Middleware();
|
||||
middleWare->Create<CookieManager>();
|
||||
middleWare->Create<SessionManager>();
|
||||
middleWare->Create<AuthWare>();
|
||||
m_RequestHandler->m_Server = this;
|
||||
};
|
||||
void Server::LoadSharedLibs() {
|
||||
|
|
@ -132,4 +136,8 @@ void Server::CreateRequest(int sockID) {
|
|||
m_RawRequest.Remove(sockID);
|
||||
m_RequestHandler->AddRequest(request);
|
||||
}
|
||||
|
||||
Ref<MiddleWareHandler> &Server::Middleware() {
|
||||
return m_RequestHandler->Middleware();
|
||||
}
|
||||
} // namespace VWeb
|
||||
Loading…
Add table
Add a link
Reference in a new issue