Added basic rest framework

This commit is contained in:
Leon Etienne (ubuntu wsl) 2020-09-24 14:31:30 +02:00
parent 918b735922
commit 595e04bc32
20 changed files with 429 additions and 318 deletions

View File

@ -1,6 +1,7 @@
#include "Framework.h"
using namespace Logging;
using namespace Rest;
Framework::Framework()
{
@ -13,7 +14,7 @@ Framework::Framework()
PostInit();
isRunning = true;
XGControl::keepServerRunning = true;
Run();
return;
@ -32,7 +33,7 @@ Framework::~Framework()
void Framework::Run()
{
while (isRunning)
while (XGControl::keepServerRunning)
{
restInterface->Update();
}
@ -48,6 +49,7 @@ void Framework::Run()
void Framework::PreInit()
{
LogHistory::PreInit();
RestQueryHandler::PreInit();
return;
}
@ -70,6 +72,7 @@ void Framework::OnExit()
void Framework::PostExit()
{
LogHistory::PostExit();
RestQueryHandler::PostExit();
return;
}

View File

@ -2,6 +2,7 @@
#include "Logger.h"
#include "LogHistory.h"
#include "RestInterface.h"
#include "XGControl.h"
class Framework
{
@ -9,18 +10,17 @@ public:
Framework();
~Framework();
void Run();
private:
void Run();
void PostInit();
void OnExit();
void PreInit();
void PostExit();
RestInterface* restInterface;
Rest::RestInterface* restInterface;
Log* log;
Logging::Logger* log;
bool isRunning = true;
};

View File

@ -948,6 +948,7 @@ void JsonArray::Parse(const std::string jsonCode)
bool areWeInString = false;
bool areWeInCode = false;
bool isCharEscaped = false;
bool areWeBetweenCommaAndValue = false; // Has the parser found a comma, but is still looking for the next value?
for (std::size_t i = 0; i < minifiedCode.length(); i++)
{
@ -957,13 +958,25 @@ void JsonArray::Parse(const std::string jsonCode)
{
start = i;
areWeInCode = true;
areWeBetweenCommaAndValue = true;
}
else if ((!areWeInString) && (areWeInCode) && (arrayBracketLevel == 1) && (curlyBracketLevel == 0) && ((c == ',') || (i == minifiedCode.length() - 1)))
{
if (c != ',') areWeBetweenCommaAndValue = false;
end = i;
areWeInCode = false;
dataJsonSnippets.push_back(minifiedCode.substr(start, end - start));
std::string codeSnippet = minifiedCode.substr(start, end - start);
if (codeSnippet.length() > 0) // A json data snippet can't be of size 0!
{
dataJsonSnippets.push_back(codeSnippet);
}
else
{
// JsonElement too short to be valid.
throw JsonParsingGeneralException(std::string("Fucked up a comma around position ") + Jstring((long long int)start));
}
}
if ((!areWeInString) && (c == ']') && (arrayBracketLevel == 1) && (i != minifiedCode.length() - 1)) throw JsonParsingExpectedEOFException(minifiedCode.substr(i, minifiedCode.length() - i));
@ -984,6 +997,7 @@ void JsonArray::Parse(const std::string jsonCode)
// Someone fucked up his json code
if (arrayBracketLevel != 0) throw JsonParsingMissingBracketsException();
if (curlyBracketLevel != 0) throw JsonParsingMissingBracketsException();
if (areWeBetweenCommaAndValue) throw JsonParsingGeneralException("Unexpected EOF. Don't put a comma after the last value of a json array!");
if (areWeInString) throw JsonParsingMissingQuotesException();
}
@ -1090,7 +1104,7 @@ std::string StringHelpers::Replace(const std::string str, const std::string find
return ss.str();
}
std::string StringHelpers::Escape(std::string str)
std::string StringHelpers::Escape(const std::string str)
{
std::stringstream ss;
@ -1120,7 +1134,6 @@ std::string StringHelpers::Escape(std::string str)
ss << "\\\\";
break;
default:
if (str[i] < 0) ss << EscapeUTF8(str[i]);
else ss << str[i];
}
@ -1671,6 +1684,11 @@ double JsonData::GetFloatPrecision() const
return customFloatPrecision;
}
bool JsonData::IsOfNumericType() const
{
return (dataType == JSON_DATA_TYPE::INT) || (dataType == JSON_DATA_TYPE::FLOAT);
}
bool JsonData::GetBoolData() const
{
JSON_DATA_TYPE typeToGet = JSON_DATA_TYPE::BOOL;
@ -2963,22 +2981,43 @@ void JsonBlock::Parse(const std::string jsonCode)
bool areWeInString = false;
bool areWeInCode = false;
bool isCharEscaped = false;
bool areWeBetweenCommaAndLabel = false; // Has the parser found a comma, but is still looking for the next label?
for (std::size_t i = 0; i < minifiedCode.length(); i++)
{
const char c = minifiedCode[i];
if ((!areWeInString) && (c == '\"') && (arrayBracketLevel == 0) && (curlyBracketLevel == 1) && (!areWeInCode))
if ((!areWeInString) && (arrayBracketLevel == 0) && (curlyBracketLevel == 1) && (!areWeInCode))
{
if (c == '\"')
{
start = i;
areWeInCode = true;
areWeBetweenCommaAndLabel = false;
}
else if (c == ',')
{
// Did not find a label between two commas!
throw JsonParsingGeneralException(std::string("Fucked up a comma around position ") + Jstring((long long int)i));
}
}
else if ((areWeInCode) && (arrayBracketLevel == 0) && (curlyBracketLevel == 1) && (!areWeInString) && ((c == ',') || (c == '}')))
{
end = i;
areWeInCode = false;
elementCodeSnippets.push_back(minifiedCode.substr(start, end - start));
if (c == ',') areWeBetweenCommaAndLabel = true;
std::string codeSnippet = minifiedCode.substr(start, end - start);
if (codeSnippet.length() >= 4) // Minimum length for valid JsonElement code. "":0
{
elementCodeSnippets.push_back(codeSnippet);
}
else
{
// JsonElement too short to be valid.
throw JsonParsingGeneralException(std::string("Fucked up a comma around position ") + Jstring((long long int)start));
}
}
// Our } at level 1 is not the last char? It should be! EXPECTED_END_OF_FILE_EXCEPTION :)
@ -2987,7 +3026,7 @@ void JsonBlock::Parse(const std::string jsonCode)
if ((c == '\"') && (!areWeInString)) areWeInString = true;
else if ((c == '\"') && (!isCharEscaped) && (areWeInString)) areWeInString = false;
// No need to check for char escaping since we are already checking if we are in a string or not. Chars are ever escaped outside of strings
// No need to check for char escaping since we are already checking if we are in a string or not. Chars are never escaped outside of strings
if ((c == '[') && (!areWeInString)) arrayBracketLevel++;
else if ((c == ']') && (!areWeInString)) arrayBracketLevel--;
else if ((c == '{') && (!areWeInString)) curlyBracketLevel++;
@ -3001,6 +3040,7 @@ void JsonBlock::Parse(const std::string jsonCode)
if (arrayBracketLevel != 0) throw JsonParsingMissingBracketsException();
if (curlyBracketLevel != 0) throw JsonParsingMissingBracketsException();
if (areWeInString) throw JsonParsingMissingQuotesException();
if (areWeBetweenCommaAndLabel) throw JsonParsingGeneralException("Unexpected EOF. Don't put a comma after the last value of a json block!");
if ((elementCodeSnippets.size() == 0) && (minifiedCode.length() > 2)) throw JsonParsingGeneralException("Found no members in json block, but code is too long for no members");
}

View File

@ -1053,7 +1053,7 @@ namespace JasonPP
/// </summary>
/// <param name="str">The original string to work in</param>
/// <returns>The string with escaped characters</returns>
static std::string Escape(std::string str);
static std::string Escape(const std::string str);
/// <summary>
/// Will unescape json strings
@ -1241,6 +1241,12 @@ namespace JasonPP
/// <returns>The json data type of this object</returns>
JSON_DATA_TYPE GetDataType() const { return dataType; };
/// <summary>
/// Returns whether or not this JsonData is either of type FLOAT or INT
/// </summary>
/// <returns>Whether or not this JsonData is either of type FLOAT or INT</returns>
bool IsOfNumericType() const;
/// <summary>
/// Returns the bool value of this element, exception if of wrong type
/// </summary>
@ -2136,7 +2142,7 @@ namespace JasonPP
};
}
#define JASONPP_VERSION (1.01)
#define JASONPP_VERSION (1.02)
namespace JasonPP
{

View File

@ -23,9 +23,9 @@ void LogHistory::PostExit()
return;
}
void LogHistory::AddLogToHistory(LogEntry* _newEntry)
void LogHistory::AddLogToHistory(LogEntry* newEntry)
{
history->push_back(_newEntry);
history->push_back(newEntry);
return;
}

View File

@ -26,7 +26,7 @@ namespace Logging
static std::vector<LogEntry*>* GetLogHistory() { return history; }
private:
static void AddLogToHistory(LogEntry* _newEntry);
static void AddLogToHistory(LogEntry* newEntry);
static std::vector<LogEntry*>* history;

View File

@ -2,15 +2,15 @@
using namespace Logging;
Logger::Logger(std::string _identifier)
Logger::Logger(std::string identifier)
{
isInitialized = true;
std::stringstream ss;
rawIdentifier = _identifier;
rawIdentifier = identifier;
ss << "[" << rawIdentifier << "]";
identifier = ss.str();
this->identifier = ss.str();
return;
}
@ -25,12 +25,12 @@ void Logger::Clear()
return;
}
void Logger::Set(std::string _str)
void Logger::Set(std::string str)
{
if (!IsInitializedSanityCheck()) return;
Clear();
cout << _str;
cout << str;
return;
}
@ -44,7 +44,7 @@ std::string Logger::Flush()
tm currTm;
localtime_s(&currTm, &currTime);
char timeBuf[256];
strftime(timeBuf, 100, "%d.%m.%Y - %T", currTm);
strftime(timeBuf, 100, "%d.%m.%Y - %T", &currTm);
std::stringstream bufOut;
bufOut << "<" << timeBuf << "> " << identifier << TypeToPrefix(type) << ": " << cout.str();
@ -56,25 +56,25 @@ std::string Logger::Flush()
newEntry->type = type;
LogHistory::AddLogToHistory(newEntry);
std::cout << TypeToColor(type) << bufOut.str() << "\033[0m" << std::endl;
std::cout << bufOut.str() << std::endl;
Clear();
return "";
}
std::string Logger::Type(LOG_TYPE _type)
std::string Logger::Type(LOG_TYPE type)
{
if (!IsInitializedSanityCheck()) return "";
type = _type;
this->type = type;
return "";
}
std::string Logger::TypeToPrefix(LOG_TYPE _type)
std::string Logger::TypeToPrefix(LOG_TYPE type)
{
switch (_type)
switch (type)
{
case LOG_TYPE::LOG:
return "";
@ -94,7 +94,7 @@ std::string Logger::TypeToPrefix(LOG_TYPE _type)
std::string Logger::TypeToColor(LOG_TYPE _type)
{
switch (_type)
/*switch (_type)
{
case LOG_TYPE::LOG:
return "\033[0m";
@ -109,7 +109,8 @@ std::string Logger::TypeToColor(LOG_TYPE _type)
return "\033[0m";
}
return "\033[0m";
return "\033[0m";*/
return "";
}
bool Logger::IsInitializedSanityCheck()
@ -117,7 +118,8 @@ bool Logger::IsInitializedSanityCheck()
if (!isInitialized)
{
Logger log("Logger"); //A Log object cannot always have a Log-member because of its recursive nature. Only create them when needed!
log.cout << log.Err() << "Attempted to use logger object without being initialized!" << log.Flush();
log.cout << log.Err() << "Attempted to use logger object without being initialized!";
log.Flush();
return false;
}

View File

@ -7,43 +7,43 @@
namespace Logging
{
class Log
class Logger
{
public:
public:
//Creates a Logger object. Pass an identifier such as MySQL
Log(std::string _identifier);
Logger(std::string identifier);
//Clears the buffered string and resets the log type to default
void Clear();
//Sets the buffered string
void Set(std::string _str);
void Set(std::string str);
//Prints the buffered string to the console and clears it
std::string Flush();
//Sets a custom log type
std::string Type(LOG_TYPE _type);
std::string Type(LOG_TYPE type);
//Sets the log type to warning
std::string Warn() { return Type(WARN); }
std::string Warn() { return Type(LOG_TYPE::WARN); }
//Sets the log type to error
std::string Err() { return Type(ERR); }
std::string Err() { return Type(LOG_TYPE::ERR); }
std::stringstream cout;
private:
std::string TypeToPrefix(LOG_TYPE _type);
std::string TypeToColor(LOG_TYPE _type);
std::string TypeToPrefix(LOG_TYPE type);
std::string TypeToColor(LOG_TYPE type);
bool IsInitializedSanityCheck();
std::string identifier;
std::string rawIdentifier;
LOG_TYPE type = LOG;
LOG_TYPE type = LOG_TYPE::LOG;
bool isInitialized = false;
};

View File

@ -1,6 +1,8 @@
#include "RestInterface.h"
using namespace Logging;
using namespace Rest;
using namespace JasonPP;
RestInterface::RestInterface()
{
@ -28,7 +30,6 @@ void RestInterface::PostInit()
{
isBootedSuccessfully = InitWebServer();
return;
}
@ -64,45 +65,42 @@ void RestInterface::Update()
return;
}
void RestInterface::ServeStringToConnection(struct mg_connection* _c, std::string _str)
void RestInterface::ServeStringToConnection(struct mg_connection* c, std::string str, int httpStatusCode)
{
mg_send_head(_c, 200, _str.length(), "content-type: application/json\nAccess-Control-Allow-Origin: *");
mg_printf(_c, _str.c_str());
mg_send_head(c, httpStatusCode, str.length(), "content-type: application/json\nAccess-Control-Allow-Origin: *");
mg_printf(c, str.c_str());
return;
}
void RestInterface::EventHandler(mg_connection* _pNc, int _ev, void* _p)
void RestInterface::EventHandler(mg_connection* pNc, int ev, void* p)
{
switch (_ev)
switch (ev)
{
case MG_EV_HTTP_REQUEST:
/*
StringParser sp(_pNc->recv_mbuf.buf);
http_message* hpm = (http_message*)p;
std::string requestBodyRaw = FixUnterminatedString(hpm->body.p, hpm->body.len);
sp.Skip("GET /");
std::string rawRequest = sp.ExtSeek(" HTTP/");
std::string jsonQuery = StringTools::UrlDecode(rawRequest);
if (IsJsonValid(requestBodyRaw))
{
Json requestBody;
requestBody.Parse(requestBodyRaw);
std::string queryResult = RestAPIQueryHandler::ProcessQuery(jsonQuery);
JsonBlock responseBody;
HTTP_STATUS_CODE returnCode;
RestQueryHandler::ProcessQuery(requestBody, responseBody, returnCode);
Json response(responseBody);
ServeStringToConnection(pNc, response.Render(), returnCode);
}
else
{
Json errorJson = RestResponseTemplates::GetByCode(HTTP_STATUS_CODE::BAD_REQUEST, "Received json is fucked up");
ServeStringToConnection(pNc, errorJson.Render(), HTTP_STATUS_CODE::BAD_REQUEST);
}
ServeStringToConnection(_pNc, queryResult);
*/
//std::cout << _pNc->recv_mbuf.buf << std::endl;
http_message* hpm = (http_message*)_p;
char buf[500];
mg_get_http_var(&hpm->body, "data", buf, 500);
std::cout << buf << std::endl;
ServeStringToConnection(_pNc, _pNc->recv_mbuf.buf);
break;
}
@ -115,3 +113,15 @@ void RestInterface::OnExit()
return;
}
std::string RestInterface::FixUnterminatedString(const char* cstr, const std::size_t len)
{
std::stringstream ss;
for (std::size_t i = 0; i < len; i++)
{
ss << *(cstr + i);
}
return ss.str();
}

View File

@ -4,10 +4,14 @@
#include <sstream>
#include "mongoose.h"
#include "Logger.h"
#include "RestResponseTemplates.h"
#include "RestQueryHandler.h"
#define WEBAPI_SERVER_POLLRATE 100
#define WEBAPI_SERVER_PORT "6969"
namespace Rest
{
class RestInterface
{
public:
@ -21,17 +25,16 @@ public:
private:
bool InitWebServer();
static void EventHandler(struct mg_connection* _pNc, int _ev, void* _p);
static void ServeStringToConnection(struct mg_connection* _c, std::string _str);
static void EventHandler(struct mg_connection* pNc, int ev, void* p);
static void ServeStringToConnection(struct mg_connection* c, std::string str, int httpStatusCode = 200);
static std::string FixUnterminatedString(const char* cstr, const std::size_t len);
struct mg_mgr* pMgr;
struct mg_connection* pNc;
static mg_serve_http_opts pServeOpts;
Logging::Logger* log;
bool isBootedSuccessfully;
};
}

View File

@ -0,0 +1,92 @@
#include "RestQueryHandler.h"
using namespace Rest;
using namespace Logging;
using namespace JasonPP;
void RestQueryHandler::PreInit()
{
log = new Logger("RestQueryHandler");
return;
}
bool RestQueryHandler::ProcessQuery(const Json& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
{
if (!ValidateField("request", JSON_DATA_TYPE::STRING, request, responseBody))
{
responseCode = BAD_REQUEST;
return false;
}
JsonBlock requestBody = request.AsJson;
std::string requestName = requestBody.Get("request").AsString;
if (requestName == "kill_yourself") return KillYourself(requestBody, responseBody, responseCode);
responseBody.CloneFrom(RestResponseTemplates::GetByCode(NOT_FOUND, "The requested request was not found."));
responseCode = NOT_FOUND;
return false;
}
void Rest::RestQueryHandler::PostExit()
{
delete log;
log = nullptr;
return;
}
bool RestQueryHandler::KillYourself(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
{
XGControl::keepServerRunning = false;
log->cout << "Shutting down server upon rest request...";
log->Flush();
responseCode = OK;
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
responseBody.Set("message") = "Goodbye! :3";
return true;
}
bool RestQueryHandler::ValidateField(const std::string name, const JasonPP::JSON_DATA_TYPE type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere)
{
if (checkThat.GetDataType() != JSON_DATA_TYPE::JSON)
{
putErrorResponseHere = RestResponseTemplates::GetByCode(BAD_REQUEST, "The request body must be a json struct! No json array or similar...");
return false;
}
const JsonBlock& cachedJson = checkThat.AsJson;
if (cachedJson.DoesShorthandExist(name))
{
const JsonData& cached = cachedJson.ShorthandGet(name);
if ((cached.GetDataType() == type) ||
((cached.IsOfNumericType()) && (type == JSON_DATA_TYPE::INT)) ||
((cached.IsOfNumericType()) && (type == JSON_DATA_TYPE::FLOAT)))
{
return true;
}
else
{
std::stringstream ss;
ss << "Mandatory value \"" << name << "\" is of wrong type (" << JsonDataType2String(cached.GetDataType()) << ")" << std::endl;
ss << "Should be of type " << JsonDataType2String(type) << "! (Integers can be casted to floats)";
putErrorResponseHere.CloneFrom(RestResponseTemplates::GetByCode(BAD_REQUEST, ss.str()));
}
}
else
{
putErrorResponseHere.CloneFrom(RestResponseTemplates::GetByCode(BAD_REQUEST, std::string("Missing mandatory value '" + name + "'")));
return false;
}
return false;
}
Logger* RestQueryHandler::log;

25
Tubio/RestQueryHandler.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "JasonPP.hpp"
#include "RestResponseTemplates.h"
#include "XGControl.h"
#include "Logger.h"
namespace Rest
{
class RestQueryHandler
{
public:
static void PreInit();
static bool ProcessQuery(const JasonPP::Json& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static void PostExit();
private:
static bool KillYourself(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
static bool ValidateField(const std::string name, const JasonPP::JSON_DATA_TYPE type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere);
static Logging::Logger* log;
};
}

View File

@ -0,0 +1,89 @@
#include "RestResponseTemplates.h"
using namespace JasonPP;
/*
Every query MUST have a value for "status"
Every query with status = "ERROR" MUST have a value for "description" and "message"!
*/
JsonBlock Rest::RestResponseTemplates::GetByCode(HTTP_STATUS_CODE code, std::string message)
{
switch (code)
{
case HTTP_STATUS_CODE::OK:
return OK();
case HTTP_STATUS_CODE::BAD_REQUEST:
return BadRequest(message);
case HTTP_STATUS_CODE::FORBIDDEN:
return Forbidden((message.length() > 0) ? message : "Could be disabled in the config file!");
case HTTP_STATUS_CODE::NOT_FOUND:
return NotFound((message.length() > 0) ? message : "not found");
case HTTP_STATUS_CODE::INTERNAL_SERVER_ERROR:
return InternalServerError((message.length() > 0) ? message : "Well, that's not good.");
case HTTP_STATUS_CODE::NOT_IMPLEMENTED:
return NotImplemented(message);
}
return InternalServerError("No template found for this http-status-code");
}
JsonBlock Rest::RestResponseTemplates::OK()
{
return JsonBlock({
Ele("status", "OK"),
});
}
JsonBlock Rest::RestResponseTemplates::BadRequest(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Bad request"),
Ele("message", message)
});
}
JsonBlock Rest::RestResponseTemplates::Unauthorized(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Unauthorized"),
Ele("message", message)
});
}
JsonBlock Rest::RestResponseTemplates::Forbidden(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Forbidden"),
Ele("message", message)
});
}
JsonBlock Rest::RestResponseTemplates::NotFound(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Not found"),
Ele("message", message)
});
}
JsonBlock Rest::RestResponseTemplates::InternalServerError(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Internal server error"),
Ele("message", message)
});
}
JsonBlock Rest::RestResponseTemplates::NotImplemented(std::string message)
{
return JsonBlock({
Ele("status", "ERROR"),
Ele("description", "Not implemented"),
Ele("message", message)
});
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "JasonPP.hpp"
namespace Rest
{
enum HTTP_STATUS_CODE {
OK = 200,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501
};
class RestResponseTemplates
{
public:
static JasonPP::JsonBlock GetByCode(HTTP_STATUS_CODE code, std::string message = "");
private:
static JasonPP::JsonBlock OK();
static JasonPP::JsonBlock BadRequest(std::string message);
static JasonPP::JsonBlock Unauthorized(std::string message);
static JasonPP::JsonBlock Forbidden(std::string message);
static JasonPP::JsonBlock NotFound(std::string message);
static JasonPP::JsonBlock MethodNotAllowed(std::string message);
static JasonPP::JsonBlock InternalServerError(std::string message);
static JasonPP::JsonBlock NotImplemented(std::string message);
};
}

View File

@ -145,7 +145,10 @@
<ClCompile Include="LogHistory.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="mongoose.c" />
<ClCompile Include="RestQueryHandler.cpp" />
<ClCompile Include="RestResponseTemplates.cpp" />
<ClCompile Include="RestInterface.cpp" />
<ClCompile Include="XGControl.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Framework.h" />
@ -154,7 +157,10 @@
<ClInclude Include="LogHistory.h" />
<ClInclude Include="LogTypes.h" />
<ClInclude Include="mongoose.h" />
<ClInclude Include="RestQueryHandler.h" />
<ClInclude Include="RestResponseTemplates.h" />
<ClInclude Include="RestInterface.h" />
<ClInclude Include="XGControl.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -39,6 +39,15 @@
<ClCompile Include="RestInterface.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="RestResponseTemplates.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="RestQueryHandler.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="XGControl.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="JasonPP.hpp">
@ -62,5 +71,14 @@
<ClInclude Include="RestInterface.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="RestResponseTemplates.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="RestQueryHandler.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="XGControl.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
</Project>

3
Tubio/XGControl.cpp Normal file
View File

@ -0,0 +1,3 @@
#include "XGControl.h"
bool XGControl::keepServerRunning = false;

11
Tubio/XGControl.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
/// <summary>
/// Class to house control variables
/// </summary>
class XGControl
{
public:
static bool keepServerRunning;
};

View File

@ -1,116 +0,0 @@
#include "RestInterface.h"
using namespace Logging;
RestInterface::RestInterface()
{
pMgr = new mg_mgr();
pNc = nullptr;
log = new Logger("WebServer");
isBootedSuccessfully = false;
return;
}
RestInterface::~RestInterface()
{
delete pMgr;
delete log;
log = nullptr;
pMgr = nullptr;
return;
}
void RestInterface::PostInit()
{
isBootedSuccessfully = InitWebServer();
return;
}
bool RestInterface::InitWebServer()
{
mg_mgr_init(pMgr, NULL);
log->cout << "Starting web server on port " << WEBAPI_SERVER_PORT << "...";
log->Flush();
pNc = mg_bind(pMgr, WEBAPI_SERVER_PORT, this->EventHandler);
if (pNc == NULL)
{
log->cout << log->Err() << "Failed to boot the web server! - Unable to bind listener!";
log->Flush();
return false;
}
mg_set_protocol_http_websocket(pNc);
log->cout << "Started web server successfully!";
log->Flush();
isBootedSuccessfully = true;
return true;
}
void RestInterface::Update()
{
mg_mgr_poll(pMgr, WEBAPI_SERVER_POLLRATE);
return;
}
void RestInterface::ServeStringToConnection(struct mg_connection* _c, std::string _str)
{
mg_send_head(_c, 200, _str.length(), "content-type: application/json\nAccess-Control-Allow-Origin: *");
mg_printf(_c, _str.c_str());
return;
}
void RestInterface::EventHandler(mg_connection* _pNc, int _ev, void* _p)
{
switch (_ev)
{
case MG_EV_HTTP_REQUEST:
/*
StringParser sp(_pNc->recv_mbuf.buf);
sp.Skip("GET /");
std::string rawRequest = sp.ExtSeek(" HTTP/");
std::string jsonQuery = StringTools::UrlDecode(rawRequest);
std::string queryResult = RestAPIQueryHandler::ProcessQuery(jsonQuery);
ServeStringToConnection(_pNc, queryResult);
*/
//std::cout << _pNc->recv_mbuf.buf << std::endl;
http_message* hpm = (http_message*)_p;
char buf[500];
mg_get_http_var(&hpm->body, "data", buf, 500);
ServeStringToConnection(_pNc, _pNc->recv_mbuf.buf);
break;
}
return;
}
void RestInterface::OnExit()
{
mg_mgr_free(pMgr);
return;
}

View File

@ -1,114 +0,0 @@
#include "RestInterface.h"
using namespace Logging;
RestInterface::RestInterface()
{
pMgr = new mg_mgr();
pNc = nullptr;
log = new Logger("WebServer");
isBootedSuccessfully = false;
return;
}
RestInterface::~RestInterface()
{
delete pMgr;
delete log;
log = nullptr;
pMgr = nullptr;
return;
}
void RestInterface::PostInit()
{
isBootedSuccessfully = InitWebServer();
return;
}
bool RestInterface::InitWebServer()
{
mg_mgr_init(pMgr, NULL);
log->cout << "Starting web server on port " << WEBAPI_SERVER_PORT << "...";
log->Flush();
pNc = mg_bind(pMgr, WEBAPI_SERVER_PORT, this->EventHandler);
if (pNc == NULL)
{
log->cout << log->Err() << "Failed to boot the web server! - Unable to bind listener!";
log->Flush();
return false;
}
mg_set_protocol_http_websocket(pNc);
log->cout << "Started web server successfully!";
log->Flush();
isBootedSuccessfully = true;
return true;
}
void RestInterface::Update()
{
mg_mgr_poll(pMgr, WEBAPI_SERVER_POLLRATE);
return;
}
void RestInterface::ServeStringToConnection(struct mg_connection* _c, std::string _str)
{
mg_send_head(_c, 200, _str.length(), "content-type: application/json\nAccess-Control-Allow-Origin: *");
mg_printf(_c, _str.c_str());
return;
}
void RestInterface::EventHandler(mg_connection* _pNc, int _ev, void* _p)
{
switch (_ev)
{
case MG_EV_HTTP_REQUEST:
/*
StringParser sp(_pNc->recv_mbuf.buf);
sp.Skip("GET /");
std::string rawRequest = sp.ExtSeek(" HTTP/");
std::string jsonQuery = StringTools::UrlDecode(rawRequest);
std::string queryResult = RestAPIQueryHandler::ProcessQuery(jsonQuery);
ServeStringToConnection(_pNc, queryResult);
*/
std::cout << _pNc->recv_mbuf.buf << std::endl;
http_message* hpm = (http_message*)_p;
std::cout << hpm << std::endl;
ServeStringToConnection(_pNc, _pNc->recv_mbuf.buf);
break;
}
return;
}
void RestInterface::OnExit()
{
mg_mgr_free(pMgr);
return;
}