Split VWeb into smaller headers
We have no make install support... so we don't need to have everything as a single-header and lib file.
This commit is contained in:
parent
4367534a33
commit
5bb68a7d02
43 changed files with 902 additions and 685 deletions
5
.gitattributes
vendored
Normal file
5
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
* text=auto
|
||||
*.txt text
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.hpp text
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ build-debug/
|
|||
release-build/
|
||||
build-release/
|
||||
cmake-build-debug/
|
||||
cmake-build-debug-wsl/
|
||||
.idea/
|
||||
|
||||
example/build
|
||||
|
|
|
|||
|
|
@ -8,21 +8,15 @@ set(CMAKE_CXX_STANDARD 20)
|
|||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUGSOFT")
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
set(SOURCE_FILES
|
||||
Source/EPollManager.cpp
|
||||
Source/RequestHandler.cpp
|
||||
Source/Server.cpp
|
||||
Source/SocketManager.cpp
|
||||
Source/ThreadPool.cpp
|
||||
Source/Router.cpp
|
||||
Source/MiddleWare.cpp
|
||||
Source/Route.cpp
|
||||
Source/StringUtils.cpp
|
||||
Source/Cookie.cpp
|
||||
Source/Session.cpp
|
||||
Source/Response.cpp
|
||||
Source/InbuildMiddleWare.cpp)
|
||||
|
||||
include(CMakeMacros.txt)
|
||||
|
||||
add_subdirectory(Source)
|
||||
add_subdirectory(Includes)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/)
|
||||
get_property(source_files GLOBAL PROPERTY SRCS)
|
||||
set(SOURCE_FILES ${source_files})
|
||||
add_library(VWeb ${SOURCE_FILES})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
|
@ -31,7 +25,9 @@ set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
|||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
|
||||
|
||||
install(FILES VWeb.h DESTINATION include/VWeb-${version})
|
||||
get_property(header_files GLOBAL PROPERTY Headers)
|
||||
|
||||
install(FILES ${header_files} DESTINATION include/VWeb-${version})
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
LIBRARY DESTINATION lib/$<CONFIG>
|
||||
|
|
|
|||
25
CMakeMacros.txt
Normal file
25
CMakeMacros.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
macro(add_sources)
|
||||
get_property(tmp GLOBAL PROPERTY SRCS)
|
||||
file(RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach (_src ${ARGN})
|
||||
if (_relPath)
|
||||
list(APPEND tmp "${_relPath}/${_src}")
|
||||
else ()
|
||||
list(APPEND tmp "${_src}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
set_property(GLOBAL PROPERTY SRCS ${tmp})
|
||||
endmacro()
|
||||
|
||||
macro(add_headers)
|
||||
get_property(tmp GLOBAL PROPERTY Headers)
|
||||
file(RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach (_src ${ARGN})
|
||||
if (_relPath)
|
||||
list(APPEND tmp "${_relPath}/${_src}")
|
||||
else ()
|
||||
list(APPEND tmp "${_src}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
set_property(GLOBAL PROPERTY Headers ${tmp})
|
||||
endmacro()
|
||||
24
Includes/CMakeLists.txt
Normal file
24
Includes/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
add_headers(
|
||||
Cookie.h
|
||||
EPollManager.h
|
||||
Http.h
|
||||
Map.h
|
||||
MiddleWare.h
|
||||
MiddleWareHandler.h
|
||||
ParameterValue.h
|
||||
PreMiddleWare.h
|
||||
Queue.h
|
||||
Request.h
|
||||
RequestHandler.h
|
||||
Response.h
|
||||
Route.h
|
||||
Router.h
|
||||
Server.h
|
||||
ServerConfig.h
|
||||
Session.h
|
||||
Socket.h
|
||||
SocketManager.h
|
||||
ThreadPool.h
|
||||
Types.h
|
||||
VWeb.h
|
||||
)
|
||||
35
Includes/Cookie.h
Normal file
35
Includes/Cookie.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace VWeb {
|
||||
enum class CookieSameSite { Invalid = 0, Strict, Lax, None };
|
||||
struct Cookie {
|
||||
std::string Name{};
|
||||
std::string Value{};
|
||||
std::string Expires{};
|
||||
int MaxAge{};
|
||||
std::string Domain{};
|
||||
std::string Path{"/"};
|
||||
bool Secure{};
|
||||
bool HttpOnly{};
|
||||
CookieSameSite SameSite{CookieSameSite::Strict};
|
||||
bool IsOld = false;
|
||||
};
|
||||
struct Cookies {
|
||||
public:
|
||||
void Remove(const std::string &name);
|
||||
bool Has(const std::string &name) const;
|
||||
Cookie &Get(const std::string &name) { return Data[name]; };
|
||||
std::string TransformToHeader();
|
||||
void CreateCookieFromString(const std::string &data);
|
||||
void CreateOld(const std::string &name, const std::string &value);
|
||||
|
||||
std::unordered_map<std::string, Cookie> Data;
|
||||
Cookie &operator[](const std::string &name) { return Data[name]; }
|
||||
|
||||
protected:
|
||||
static void CookieToString(std::stringstream &stream, Cookie &cookie);
|
||||
};
|
||||
} // namespace VWeb
|
||||
17
Includes/EPollManager.h
Normal file
17
Includes/EPollManager.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
namespace VWeb {
|
||||
class EPollManager {
|
||||
public:
|
||||
EPollManager();
|
||||
~EPollManager();
|
||||
[[nodiscard]] bool Dispatch(int sock, uint32_t eventType = EPOLLIN) const;
|
||||
[[nodiscard]] bool UpdateEvents(int sock, uint32_t eventType = EPOLLIN) const;
|
||||
int Wait(int idx, epoll_event *events) const;
|
||||
|
||||
protected:
|
||||
int m_EpollID{-1};
|
||||
};
|
||||
}
|
||||
76
Includes/Http.h
Normal file
76
Includes/Http.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
|
||||
namespace VWeb {
|
||||
enum class HttpStatusCode : int {
|
||||
Continue = 100,
|
||||
SwitchingProtocols = 101,
|
||||
Processing = 102,
|
||||
EarlyHints = 103,
|
||||
OK = 200,
|
||||
Created = 201,
|
||||
Accepted = 202,
|
||||
NonAuthoritativeInformation = 203,
|
||||
NoContent = 204,
|
||||
ResetContent = 205,
|
||||
PartialContent = 206,
|
||||
MultiStatus = 207,
|
||||
AlreadyReported = 208,
|
||||
IMUsed = 226,
|
||||
MultipleChoices = 300,
|
||||
MovedPermanently = 301,
|
||||
Found = 302,
|
||||
SeeOther = 303,
|
||||
NotModified = 304,
|
||||
UseProxy = 305,
|
||||
TemporaryRedirect = 307,
|
||||
PermanentRedirect = 308,
|
||||
BadRequest = 400,
|
||||
Unauthorized = 401,
|
||||
PaymentRequired = 402,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
MethodNotAllowed = 405,
|
||||
NotAcceptable = 406,
|
||||
ProxyAuthenticationRequired = 407,
|
||||
RequestTimeout = 408,
|
||||
Conflict = 409,
|
||||
Gone = 410,
|
||||
LengthRequired = 411,
|
||||
PreconditionFailed = 412,
|
||||
PayloadTooLarge = 413,
|
||||
URITooLong = 414,
|
||||
UnsupportedMediaType = 415,
|
||||
RangeNotSatisfiable = 416,
|
||||
ExpectationFailed = 417,
|
||||
ImATeapot = 418,
|
||||
UnprocessableEntity = 422,
|
||||
Locked = 423,
|
||||
FailedDependency = 424,
|
||||
UpgradeRequired = 426,
|
||||
PreconditionRequired = 428,
|
||||
TooManyRequests = 429,
|
||||
RequestHeaderFieldsTooLarge = 431,
|
||||
UnavailableForLegalReasons = 451,
|
||||
InternalServerError = 500,
|
||||
NotImplemented = 501,
|
||||
BadGateway = 502,
|
||||
ServiceUnavailable = 503,
|
||||
GatewayTimeout = 504,
|
||||
HTTPVersionNotSupported = 505,
|
||||
VariantAlsoNegotiates = 506,
|
||||
InsufficientStorage = 507,
|
||||
LoopDetected = 508,
|
||||
NotExtended = 510,
|
||||
NetworkAuthenticationRequired = 511
|
||||
};
|
||||
enum class HttpMethod {
|
||||
GET = 0,
|
||||
HEAD,
|
||||
OPTIONS,
|
||||
POST,
|
||||
PUT,
|
||||
PATCH,
|
||||
DELETE,
|
||||
FALLBACK
|
||||
};
|
||||
} // namespace VWeb
|
||||
59
Includes/Map.h
Normal file
59
Includes/Map.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
namespace VWeb {
|
||||
template <typename T, typename S> struct SafeMap {
|
||||
explicit SafeMap(size_t maxSize = -1UL) : m_MaxSize(maxSize), m_End(false){};
|
||||
bool Add(const T &t, S &x) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
while (m_Data.size() == m_MaxSize && !m_End)
|
||||
return false;
|
||||
assert(!m_End);
|
||||
m_Data.emplace(t, std::move(x));
|
||||
return true;
|
||||
};
|
||||
bool Add(T &&t, S &&x) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
while (m_Data.size() == m_MaxSize && !m_End)
|
||||
return false;
|
||||
assert(!m_End);
|
||||
m_Data.push(std::move(t));
|
||||
return true;
|
||||
};
|
||||
void Remove(T t) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
if (m_Data.empty() || m_End)
|
||||
return;
|
||||
if (m_Data.contains(t))
|
||||
m_Data.erase(t);
|
||||
m_CVFull.notify_one();
|
||||
};
|
||||
void Clear() {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
std::unordered_map<T, S> empty;
|
||||
std::swap(m_Data, empty);
|
||||
m_CVFull.notify_all();
|
||||
};
|
||||
bool Has(T t) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
return m_Data.contains(t);
|
||||
};
|
||||
S &Get(T t) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
return m_Data[t];
|
||||
};
|
||||
int Size() { return m_Data.size(); };
|
||||
|
||||
private:
|
||||
std::unordered_map<T, S> m_Data{};
|
||||
std::mutex m_Mutex{};
|
||||
std::condition_variable m_CVFull{};
|
||||
const size_t m_MaxSize{};
|
||||
std::atomic<bool> m_End{};
|
||||
};
|
||||
}
|
||||
16
Includes/MiddleWare.h
Normal file
16
Includes/MiddleWare.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include "Response.h"
|
||||
#include "Request.h"
|
||||
|
||||
namespace VWeb {
|
||||
typedef std::optional<Ref<Response>> PreMiddleWareReturn;
|
||||
struct MiddleWare {
|
||||
int Pos{0};
|
||||
virtual PreMiddleWareReturn PreHandle(Request &) { return {}; }
|
||||
virtual bool PostHandle(Request &, Response &) { return true; }
|
||||
virtual void Shutdown(Request &, const Response &){};
|
||||
bool operator<(const MiddleWare *rhs) const { return Pos < rhs->Pos; }
|
||||
};
|
||||
}
|
||||
43
Includes/MiddleWareHandler.h
Normal file
43
Includes/MiddleWareHandler.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "MiddleWare.h"
|
||||
#include "Request.h"
|
||||
#include "Response.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace VWeb {
|
||||
|
||||
class MiddleWareHandler {
|
||||
public:
|
||||
PreMiddleWareReturn HandlePre(Ref<Request> &);
|
||||
void HandlePost(Ref<Request> &, Ref<Response> &);
|
||||
void Shutdown(Ref<Request> &, Ref<Response> &);
|
||||
|
||||
public:
|
||||
template <class T> Ref<MiddleWare> GetRef() {
|
||||
return GetById(typeid(T).name());
|
||||
}
|
||||
template <class T> T &Get() {
|
||||
return static_cast<T &>(*GetById(typeid(T).name()));
|
||||
}
|
||||
template <class T> void Set(Ref<MiddleWare> &instance) {
|
||||
auto &type = typeid(T);
|
||||
if (type.before(typeid(MiddleWare)))
|
||||
SetById(type.name(), instance);
|
||||
}
|
||||
template <class T> T &Create() {
|
||||
return static_cast<T &>(*CreateMiddleWare<T>());
|
||||
}
|
||||
template <class T> void Remove() { RemoveById(typeid(T).name()); }
|
||||
|
||||
protected:
|
||||
template <class T> Ref<MiddleWare> CreateMiddleWare() {
|
||||
return SetById(typeid(T).name(), CreateRef<T>());
|
||||
}
|
||||
Ref<MiddleWare> GetById(const char *id);
|
||||
Ref<MiddleWare> SetById(const char *id, const Ref<MiddleWare> &);
|
||||
void RemoveById(const char *id);
|
||||
std::map<std::string, Ref<MiddleWare>> m_MiddleWares;
|
||||
};
|
||||
} // namespace VWeb
|
||||
21
Includes/ParameterValue.h
Normal file
21
Includes/ParameterValue.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace VWeb {
|
||||
struct ParameterValue {
|
||||
void Add(const std::string &item) { m_Data.push_back(item); }
|
||||
void Set(const std::string &item) {
|
||||
m_Data.clear();
|
||||
m_Data.push_back(item);
|
||||
}
|
||||
std::string &Get(int item) { return m_Data[item]; }
|
||||
std::string &GetFirst() { return Get(0); }
|
||||
size_t Size() { return m_Data.size(); }
|
||||
std::vector<std::string> &Values() { return m_Data; }
|
||||
|
||||
protected:
|
||||
std::vector<std::string> m_Data{};
|
||||
};
|
||||
}
|
||||
48
Includes/PreMiddleWare.h
Normal file
48
Includes/PreMiddleWare.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include "MiddleWare.h"
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
|
||||
namespace VWeb {
|
||||
typedef std::function<PreMiddleWareReturn(Request &req)> AuthFunction;
|
||||
class AuthWare : public MiddleWare {
|
||||
public:
|
||||
AuthWare() = default;
|
||||
~AuthWare() = default;
|
||||
PreMiddleWareReturn PreHandle(Request &request) override;
|
||||
void SetAuthMethod(AuthFunction function) {
|
||||
m_AuthFunction = std::move(function);
|
||||
}
|
||||
|
||||
protected:
|
||||
AuthFunction m_AuthFunction{nullptr};
|
||||
};
|
||||
|
||||
class SessionManager : public MiddleWare {
|
||||
public:
|
||||
SessionManager();
|
||||
~SessionManager();
|
||||
PreMiddleWareReturn PreHandle(Request &request) override;
|
||||
bool PostHandle(Request &request, Response &response) override;
|
||||
|
||||
protected:
|
||||
void GC();
|
||||
|
||||
protected:
|
||||
Ref<std::thread> m_GCThread;
|
||||
std::mutex m_Mutex;
|
||||
std::unordered_map<std::string, Ref<Session>> m_Sessions;
|
||||
int m_Counter{-1};
|
||||
bool m_IsRunning{true};
|
||||
};
|
||||
|
||||
class CookieManager : public MiddleWare {
|
||||
public:
|
||||
CookieManager() = default;
|
||||
~CookieManager() = default;
|
||||
PreMiddleWareReturn PreHandle(Request &) override;
|
||||
};
|
||||
} // namespace VWeb
|
||||
87
Includes/Queue.h
Normal file
87
Includes/Queue.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <optional>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
|
||||
namespace VWeb {
|
||||
template <typename T> struct SafeQueue {
|
||||
explicit SafeQueue(size_t maxSize = -1UL)
|
||||
: m_MaxSize(maxSize),
|
||||
m_End(false){};
|
||||
void Push(const T &t) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
while (m_Queue.size() == m_MaxSize && !m_End)
|
||||
m_CVFull.wait(lck);
|
||||
assert(!m_End);
|
||||
m_Queue.push(std::move(t));
|
||||
m_CVEmpty.notify_one();
|
||||
};
|
||||
void Push(T &&t) {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
while (m_Queue.size() == m_MaxSize && !m_End)
|
||||
m_CVFull.wait(lck);
|
||||
assert(!m_End);
|
||||
m_Queue.push(std::move(t));
|
||||
m_CVEmpty.notify_one();
|
||||
};
|
||||
void Open() {
|
||||
m_End = false;
|
||||
std::lock_guard<std::mutex> lck(m_Mutex);
|
||||
m_CVEmpty.notify_all();
|
||||
m_CVFull.notify_all();
|
||||
};
|
||||
void Close() {
|
||||
m_End = true;
|
||||
std::lock_guard<std::mutex> lck(m_Mutex);
|
||||
m_CVEmpty.notify_all();
|
||||
m_CVFull.notify_all();
|
||||
};
|
||||
void Clear() {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
std::queue<T> empty;
|
||||
std::swap(m_Queue, empty);
|
||||
m_CVEmpty.notify_all();
|
||||
m_CVFull.notify_all();
|
||||
};
|
||||
std::optional<T> Pop() {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
if (m_Queue.empty() || m_End)
|
||||
return {};
|
||||
T t = std::move(m_Queue.front());
|
||||
m_Queue.pop();
|
||||
m_CVFull.notify_one();
|
||||
return t;
|
||||
};
|
||||
std::optional<T> WaitAndPop() {
|
||||
std::unique_lock<std::mutex> lck(m_Mutex);
|
||||
while (m_Queue.empty() && !m_End)
|
||||
m_CVEmpty.wait(lck);
|
||||
if (m_Queue.empty() || m_End)
|
||||
return {};
|
||||
T t = std::move(m_Queue.front());
|
||||
m_Queue.pop();
|
||||
m_CVFull.notify_one();
|
||||
return t;
|
||||
};
|
||||
bool IsClosed() { return m_End; }
|
||||
int Size() { return m_Queue.size(); }
|
||||
std::queue<T> &GetQueue() { return m_Queue; }
|
||||
void Flush() {
|
||||
while (!m_Queue.empty())
|
||||
m_CVEmpty.notify_one();
|
||||
m_End = true;
|
||||
m_CVEmpty.notify_all();
|
||||
}
|
||||
|
||||
private:
|
||||
std::queue<T> m_Queue;
|
||||
std::mutex m_Mutex;
|
||||
std::condition_variable m_CVEmpty, m_CVFull;
|
||||
const size_t m_MaxSize;
|
||||
std::atomic<bool> m_End;
|
||||
};
|
||||
}
|
||||
34
Includes/Request.h
Normal file
34
Includes/Request.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "Cookie.h"
|
||||
#include "Http.h"
|
||||
#include "ParameterValue.h"
|
||||
#include "Session.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace VWeb {
|
||||
struct Request {
|
||||
public:
|
||||
int ID;
|
||||
std::string Body;
|
||||
HttpMethod Method{HttpMethod::GET};
|
||||
std::string URI;
|
||||
Ref<Session> SessionData;
|
||||
Ref<Cookies> CookieData;
|
||||
Cookie &GetCookie(const std::string &key) { return CookieData->Get(key); };
|
||||
ParameterValue &Parameter(const std::string &key) { return Parameters[key]; }
|
||||
bool HasParameter(const std::string &key) const {
|
||||
return Parameters.contains(key);
|
||||
}
|
||||
bool HasHeader(const std::string &key) const { return Headers.contains(key); }
|
||||
std::string &FirstOf(const std::string &key) {
|
||||
return Parameters[key].GetFirst();
|
||||
}
|
||||
ParameterValue &Header(const std::string &key) { return Headers[key]; }
|
||||
std::unordered_map<std::string, ParameterValue> Parameters;
|
||||
std::unordered_map<std::string, ParameterValue> Headers;
|
||||
std::vector<std::string> URLParameters;
|
||||
};
|
||||
} // namespace VWeb
|
||||
42
Includes/RequestHandler.h
Normal file
42
Includes/RequestHandler.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include "MiddleWareHandler.h"
|
||||
#include "Queue.h"
|
||||
#include "Request.h"
|
||||
#include "Router.h"
|
||||
#include "SocketManager.h"
|
||||
#include "ThreadPool.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace VWeb {
|
||||
class Server;
|
||||
typedef std::function<const void(Request &, const std::string &body)>
|
||||
ParseFunction;
|
||||
class RequestHandler {
|
||||
public:
|
||||
explicit RequestHandler(const Ref<SocketManager> &manager);
|
||||
void InitThreads(int count);
|
||||
void AddRequest(Ref<Request> &request);
|
||||
void Stop();
|
||||
void SetRouter(Ref<Router> &router);
|
||||
void AddSendResponse(SendData);
|
||||
Ref<MiddleWareHandler> &Middleware() { return m_MiddleWare; }
|
||||
bool HasBodyParser(const std::string &key) {
|
||||
return m_ParseFunctions.contains(key);
|
||||
}
|
||||
ParseFunction &GetBodyParser(const std::string &key) {
|
||||
return m_ParseFunctions.at(key);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unordered_map<std::string, ParseFunction> m_ParseFunctions;
|
||||
Ref<Router> m_Router{nullptr};
|
||||
Ref<SocketManager> m_SocketManager{nullptr};
|
||||
Server *m_Server{nullptr};
|
||||
SafeQueue<Ref<Request>> m_Requests{};
|
||||
ThreadPool m_Pool{"RequestHandler"};
|
||||
Ref<MiddleWareHandler> m_MiddleWare{nullptr};
|
||||
friend Server;
|
||||
};
|
||||
} // namespace VWeb
|
||||
43
Includes/Response.h
Normal file
43
Includes/Response.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "Cookie.h"
|
||||
#include "Http.h"
|
||||
#include "Session.h"
|
||||
#include "Types.h"
|
||||
#include "ParameterValue.h"
|
||||
|
||||
namespace VWeb {
|
||||
class Response {
|
||||
public:
|
||||
static Ref<Response> FromCode(HttpStatusCode code);
|
||||
|
||||
public:
|
||||
size_t Length{0};
|
||||
Ref<Cookies> CookieData{nullptr};
|
||||
Ref<Session> SessionData{nullptr};
|
||||
HttpStatusCode Status{HttpStatusCode::OK};
|
||||
HttpMethod Method{HttpMethod::GET};
|
||||
|
||||
public:
|
||||
std::string GetResponse();
|
||||
void SetHeader(const std::string &key, ParameterValue &value);
|
||||
void SetHeader(const std::string &key, const std::string &value);
|
||||
void AddHeaders(const std::string &key, const std::vector<std::string> &values);
|
||||
void AddHeader(const std::string &key, const std::string &value);
|
||||
void SetType(const std::string &type);
|
||||
void AddContent(const std::string &data);
|
||||
void SetStatus(HttpStatusCode);
|
||||
void SetMethod(HttpMethod);
|
||||
void Reset();
|
||||
Response &operator<<(const std::string &data) {
|
||||
m_Content << data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string TransformHeaders(const std::string &content);
|
||||
std::string m_Type{"text/html"};
|
||||
std::stringstream m_Content;
|
||||
std::unordered_map<std::string, ParameterValue> m_Headers;
|
||||
};
|
||||
} // namespace VWeb
|
||||
34
Includes/Route.h
Normal file
34
Includes/Route.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "Http.h"
|
||||
#include <initializer_list>
|
||||
#include "Request.h"
|
||||
#include "Response.h"
|
||||
#include <vector>
|
||||
|
||||
namespace VWeb {
|
||||
class Router;
|
||||
class Route {
|
||||
public:
|
||||
Route() = default;
|
||||
virtual ~Route() = default;
|
||||
Route(std::initializer_list<HttpMethod>);
|
||||
virtual bool Execute(Request &request, Response &response);
|
||||
virtual bool Get(Request &request, Response &response);
|
||||
virtual bool Post(Request &request, Response &response);
|
||||
virtual bool Put(Request &request, Response &response);
|
||||
virtual bool Patch(Request &request, Response &response);
|
||||
virtual bool Delete(Request &request, Response &response);
|
||||
bool Options(Request &request, Response &response);
|
||||
virtual bool Fallback(Request &request, Response &response);
|
||||
bool SupportsMethod(Request &request);
|
||||
virtual bool IsAllowed(Request &request);
|
||||
|
||||
void AllowMethod(HttpMethod method);
|
||||
|
||||
protected:
|
||||
bool m_AllowAll{true};
|
||||
std::vector<HttpMethod> m_AllowedMethods;
|
||||
friend Router;
|
||||
};
|
||||
}
|
||||
29
Includes/Router.h
Normal file
29
Includes/Router.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "Route.h"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace VWeb {
|
||||
typedef std::function<bool(Request &, Response &)> RouteFunction;
|
||||
class Router {
|
||||
public:
|
||||
Router();
|
||||
void AddRoute(const std::string &name, const Ref<Route> &route);
|
||||
Ref<Route> &GetRoute(const std::string &name);
|
||||
void DeleteRoute(const std::string &name);
|
||||
|
||||
Ref<Response> HandleRoute(Ref<Request> &request);
|
||||
Ref<Route> FindRoute(Ref<Request> &request);
|
||||
static void AddToArgs(Ref<Request> &request, std::vector<std::string> &items);
|
||||
|
||||
public:
|
||||
void Get(const std::string &path, RouteFunction);
|
||||
void Post(const std::string &path, RouteFunction);
|
||||
void Put(const std::string &path, RouteFunction);
|
||||
void Patch(const std::string &path, RouteFunction);
|
||||
void Delete(const std::string &path, RouteFunction);
|
||||
std::unordered_map<std::string, Ref<Route>> m_Routes;
|
||||
};
|
||||
} // namespace VWeb
|
||||
49
Includes/Server.h
Normal file
49
Includes/Server.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "EPollManager.h"
|
||||
#include "SocketManager.h"
|
||||
#include "Map.h"
|
||||
#include "Router.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "MiddleWareHandler.h"
|
||||
#include "Route.h"
|
||||
|
||||
namespace VWeb {
|
||||
class Server {
|
||||
public:
|
||||
Server();
|
||||
// Will Load SharedLibs from subdirectory
|
||||
// This will allow that VWeb will run as Standalone and will load .so files
|
||||
// without recompiling itself
|
||||
void LoadSharedLibs();
|
||||
void Start();
|
||||
void Join() { m_WorkerThread->join(); }
|
||||
void Stop() { m_IsExit = true; }
|
||||
Ref<Router> &GetRouter() { return m_Router; }
|
||||
Ref<ServerConfig> &GetServerConfig() { return m_ServerConfig; }
|
||||
void AddRoute(const std::string &path, const Ref<Route> &route);
|
||||
void RemoveRoute(const std::string &path);
|
||||
|
||||
Ref<MiddleWareHandler> &Middleware();
|
||||
|
||||
protected:
|
||||
void Execute();
|
||||
void OutgoingExecute(epoll_event &event);
|
||||
void IncomingExecute(epoll_event &event);
|
||||
void HandleRequestReading(epoll_event &event);
|
||||
void CreateRequest(int sockID);
|
||||
|
||||
protected:
|
||||
Ref<Router> m_Router;
|
||||
Ref<ServerConfig> m_ServerConfig;
|
||||
Ref<RequestHandler> m_RequestHandler;
|
||||
SafeMap<int, Accept> m_RawRequest{60000};
|
||||
SafeMap<int, SendData> m_OutRequest{60000};
|
||||
Ref<std::thread> m_WorkerThread;
|
||||
std::mutex m_Mutex;
|
||||
bool m_IsExit{false};
|
||||
|
||||
protected:
|
||||
friend RequestHandler;
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue