1#include "WebFramework.h"
6#include "JSONArrayWrapper.h"
8#include "Exceptions/BaseJSONException.h"
9#include "Exceptions/FileDoesNotExistException.h"
10#include "WebNetwork/WebServers/MultithreadedWebServer.h"
11#include "WebNetwork/WebServers/ThreadPoolWebServer.h"
12#include "LoadBalancer/LoadBalancerServer.h"
13#include "Utility/Singletons/HTTPSSingleton.h"
14#include "Utility/Sources.h"
15#include "Proxy/ProxyServer.h"
16#include "Utility/DynamicLibraries.h"
24 static string version =
"3.0.12";
31 return utility::HTTPSSingleton::get().getUseHTTPS();
34 uint64_t WebFramework::parseLoggingFlags(
const json::utility::jsonObject& loggingSettings)
const
36 vector<json::utility::jsonObject> flags;
38 return loggingSettings.tryGetArray(json_settings::logFlagsKey, flags) ?
39 Log::createFlags(json::utility::JSONArrayWrapper(flags).getAsStringArray()) :
40 (numeric_limits<uint64_t>::max)();
43 string WebFramework::initLogging()
const
45 json::utility::jsonObject loggingSettings;
47 if (!(*config).tryGetObject(json_settings::loggingObject, loggingSettings))
52 bool usingLogging =
false;
54 if (loggingSettings.tryGetBool(json_settings::usingLoggingKey, usingLogging) && usingLogging)
57 const string& dateFormat = loggingSettings.getString(json_settings::dateFormatKey);
58 bool duplicateOutput =
false;
59 bool duplicateErrorOutput =
false;
61 loggingSettings.tryGetString(json_settings::logsPathKey, logsPath);
63 loggingSettings.tryGetBool(json_settings::duplicateOutputKey, duplicateOutput);
64 loggingSettings.tryGetBool(json_settings::duplicateErrorOutputKey, duplicateErrorOutput);
66 uint64_t logFileSize = 0;
67 uint64_t flags = this->parseLoggingFlags(loggingSettings);
69 if (loggingSettings.tryGetUnsignedInt(json_settings::logFileSizeKey, logFileSize))
71 if (flags == (numeric_limits<uint64_t>::max)())
73 Log::configure(dateFormat, logsPath, logFileSize);
77 Log::configure(dateFormat, logsPath, logFileSize, flags);
82 if (flags == (numeric_limits<uint64_t>::max)())
84 Log::configure(dateFormat, logsPath);
88 Log::configure(dateFormat, logsPath, Log::logFileSize, flags);
94 Log::duplicateLog(cout);
97 if (duplicateErrorOutput)
99 Log::duplicateErrorLog(cerr);
106 void WebFramework::initHTTPS(
const json::utility::jsonObject& webFrameworkSettings)
const
108 json::utility::jsonObject https;
110 if (!webFrameworkSettings.tryGetObject(json_settings::httpsObject, https))
115 bool useHTTPS =
false;
117 if (https.tryGetBool(json_settings::useHTTPSKey, useHTTPS) && useHTTPS)
119 utility::HTTPSSingleton& httpsSettings = utility::HTTPSSingleton::get();
120 const filesystem::path& basePath = config.
getBasePath();
122 httpsSettings.setUseHTTPS(
true);
123 httpsSettings.setPathToCertificate(basePath / https.getString(json_settings::pathToCertificateKey));
124 httpsSettings.setPathToKey(basePath / https.getString(json_settings::pathToKey));
127 SSL_load_error_strings();
131 void WebFramework::initServer
133 const json::utility::jsonObject& webFrameworkSettings,
134 const vector<utility::JSONSettingsParser>& jsonSettings,
135 const vector<string>& pathToSources
138 const filesystem::path& basePath = config.
getBasePath();
139 const json::utility::jsonObject& webServerSettings = (*config).getObject(json_settings::webServerObject);
140 const string& ip = webServerSettings.getString(json_settings::ipKey);
141 string port = to_string(webServerSettings.getInt(json_settings::portKey));
142 DWORD timeout =
static_cast<DWORD
>(webServerSettings.getInt(json_settings::timeoutKey));
144 const string& webServerType = webFrameworkSettings.getString(json_settings::webServerTypeKey);
145 string assetsPath = (basePath / webFrameworkSettings.getString(json_settings::assetsPathKey)).string();
146 string templatesPath = (basePath / webFrameworkSettings.getString(json_settings::templatesPathKey)).string();
147 uint64_t cachingSize = webFrameworkSettings.getUnsignedInt(json_settings::cachingSize);
149 if (webServerType == json_settings::multiThreadedWebServerTypeValue)
151 server = make_unique<MultithreadedWebServer>
164 else if (webServerType == json_settings::threadPoolWebServerTypeValue)
166 int64_t threadCount = 0;
167 json::utility::jsonObject threadPoolServerObject;
169 if ((*config).tryGetObject(json_settings::threadPoolServerObject, threadPoolServerObject))
171 (*config).tryGetInt(json_settings::threadCountKey, threadCount);
174 server = make_unique<ThreadPoolWebServer>
185 static_cast<uint32_t
>(threadCount)
188 else if (webServerType == json_settings::loadBalancerWebServerTypeValue)
190 const json::utility::jsonObject& loadBalancerSettings = (*config).getObject(json_settings::loadBalancerObject);
191 const string& heuristic = loadBalancerSettings.getString(json_settings::heuristicKey);
192 const string& loadSource = loadBalancerSettings.getString(json_settings::loadSourceKey);
193 bool serversHTTPS = loadBalancerSettings.getBool(json_settings::serversHTTPSKey);
194 const json::utility::jsonObject& listOfServers = loadBalancerSettings.getObject(
"listOfServers");
195 unordered_map<string, vector<int64_t>> allServers;
197 for (
const auto& [key, value] : listOfServers)
199 allServers.try_emplace
202 json::utility::JSONArrayWrapper(get<vector<json::utility::jsonObject>>(value)).getAsInt64_tArray()
206 server = make_unique<load_balancer::LoadBalancerServer>
213 utility::loadSources(pathToSources),
221 else if (webServerType == json_settings::proxyWebServerTypeValue)
223 server = make_unique<proxy::ProxyServer>(ip, port, timeout, (*config).getObject(json_settings::proxyObject));
227 throw runtime_error(::exceptions::wrongWebServerType);
231 WebFramework::WebFramework(
const utility::Config& webFrameworkConfig) :
232 config(webFrameworkConfig)
234 const json::utility::jsonObject& webFrameworkSettings = (*config).getObject(json_settings::webFrameworkObject);
235 const filesystem::path& basePath = config.
getBasePath();
236 vector<string> settingsPaths = json::utility::JSONArrayWrapper(webFrameworkSettings.getArray(json_settings::settingsPathsKey)).getAsStringArray();
237 vector<string> pathToSources = json::utility::JSONArrayWrapper(webFrameworkSettings.getArray(json_settings::loadSourcesKey)).getAsStringArray();
239 ranges::for_each(settingsPaths, [
this, &basePath](
string& path) { path = (basePath / path).
string(); });
240 ranges::for_each(pathToSources, [
this, &basePath](
string& source)
242 if (source ==
"current")
247 source = (basePath / source).
string();
250 if (
string errorMessage = this->initLogging(); errorMessage.size())
252 throw runtime_error(errorMessage);
255 this->initHTTPS(webFrameworkSettings);
257 vector<utility::JSONSettingsParser> jsonSettings;
259 jsonSettings.reserve(settingsPaths.size());
261 transform(settingsPaths.begin(), settingsPaths.end(), back_inserter(jsonSettings), [](
const string& i) {
return utility::JSONSettingsParser(i); });
265 webFrameworkSettings,
271 WebFramework::WebFramework(
const filesystem::path& webFrameworkConfigPath) :
272 WebFramework(utility::Config(webFrameworkConfigPath))
279 server->start(wait, onStartServer);
294 vector<pair<string, vector<SOCKET>>> clients = server->getClients();
295 vector<string> result;
297 result.reserve(clients.size());
299 for (
const auto& [ip, _] : clients)
301 result.push_back(ip);
309 return server->isServerRunning();
void kick(const std::string &ip) const
Kick specific client.
void stop(bool wait=true)
Stop server.
void start(bool wait=false, const std::function< void()> &onStartServer=[]() {})
Start server.
static std::string_view getWebFrameworkVersion()
Get current WebFramework version.
bool isServerRunning() const
Is server running.
const json::JSONParser & getCurrentConfiguration() const
Getter for currentConfiguration.
std::vector< std::string > getClientsIp() const
Get ip addresses of all currently connected clients.
static bool getUseHTTPS()
Is server use HTTPS.
const std::filesystem::path & getBasePath() const
Config file directory.