From 86ec60ca0a4c4c84634b8d84d1c71e8d1ef81669 Mon Sep 17 00:00:00 2001 From: Clovis Durand Date: Wed, 8 Apr 2020 17:39:22 +0200 Subject: [PATCH] [#28] Moved RESTServer to separate repository & added it as submodule Signed-off-by: Clovis Durand --- .gitmodules | 3 + generator/deps/CMakeLists.txt | 3 +- generator/deps/RESTServer | 1 + generator/src/rest/CMakeLists.txt | 7 - generator/src/rest/inc/HTTPRequest.hpp | 124 ---------- generator/src/rest/inc/RESTServer.hpp | 100 -------- generator/src/rest/resources/webpage.cpp | 136 ---------- generator/src/rest/resources/webpage.hpp | 32 --- generator/src/rest/src/CMakeLists.txt | 84 ------- generator/src/rest/src/HTTPRequest.cpp | 226 ----------------- generator/src/rest/src/RESTServer.cpp | 302 ----------------------- generator/src/rest/src/main.cpp | 78 ------ 12 files changed, 6 insertions(+), 1090 deletions(-) create mode 160000 generator/deps/RESTServer delete mode 100644 generator/src/rest/CMakeLists.txt delete mode 100644 generator/src/rest/inc/HTTPRequest.hpp delete mode 100644 generator/src/rest/inc/RESTServer.hpp delete mode 100644 generator/src/rest/resources/webpage.cpp delete mode 100644 generator/src/rest/resources/webpage.hpp delete mode 100644 generator/src/rest/src/CMakeLists.txt delete mode 100644 generator/src/rest/src/HTTPRequest.cpp delete mode 100644 generator/src/rest/src/RESTServer.cpp delete mode 100644 generator/src/rest/src/main.cpp diff --git a/.gitmodules b/.gitmodules index cd6bef1..02c76bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "generator/deps/rapidjson"] path = generator/deps/rapidjson url = https://github.com/Tencent/rapidjson.git +[submodule "generator/deps/RESTServer"] + path = generator/deps/RESTServer + url = https://github.com/Clovel/RESTServer.git diff --git a/generator/deps/CMakeLists.txt b/generator/deps/CMakeLists.txt index 0cc8629..4352f60 100644 --- a/generator/deps/CMakeLists.txt +++ b/generator/deps/CMakeLists.txt @@ -4,4 +4,5 @@ # ----------------------------------------------------------------------------- # Sub-directories ----------------------------------------- -add_subdirectory(initools) \ No newline at end of file +add_subdirectory(initools) +add_subdirectory(RESTServer) diff --git a/generator/deps/RESTServer b/generator/deps/RESTServer new file mode 160000 index 0000000..a994578 --- /dev/null +++ b/generator/deps/RESTServer @@ -0,0 +1 @@ +Subproject commit a9945785602d5c271edf4780b3013f025d9b620b diff --git a/generator/src/rest/CMakeLists.txt b/generator/src/rest/CMakeLists.txt deleted file mode 100644 index 42ea729..0000000 --- a/generator/src/rest/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (C) 2020 Clovis Durand -# -# ----------------------------------------------------------------------------- - -# Sub-directories ----------------------------------------- -add_subdirectory(src) \ No newline at end of file diff --git a/generator/src/rest/inc/HTTPRequest.hpp b/generator/src/rest/inc/HTTPRequest.hpp deleted file mode 100644 index 4e37e17..0000000 --- a/generator/src/rest/inc/HTTPRequest.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @brief HTTPRequest class - * - * @file HTTPRequest.hpp - */ - -#ifndef HTTPREQUEST_HPP -#define HTTPREQUEST_HPP - -#endif /* HTTPREQUEST_HPP */ - -/* Includes -------------------------------------------- */ -/* C++ system */ -#include -#include -#include - -/* Defines --------------------------------------------- */ - -/* Type definitions ------------------------------------ */ -typedef enum _httpVersion { - HTTP_VERSION_UNKNOWN = 0U, - HTTP_VERSION_1_0, - HTTP_VERSION_1_1, - HTTP_VERSION_2_0 -} httpVersion_t; - -typedef enum _httpMethods { - HTTP_METHOD_UNKNOWN = 0U, - HTTP_METHOD_GET, - HTTP_METHOD_HEAD, - HTTP_METHOD_POST, - HTTP_METHOD_PUT, - HTTP_METHOD_DELETE, - HTTP_METHOD_CONNECT, - HTTP_METHOD_OPTIONS, - HTTP_METHOD_TRACE, - HTTP_METHOD_PATCH -} httpMethod_t; - -typedef std::vector httpBody_t; - -/* Forward declarations -------------------------------- */ - -/* HTTPRequest exception ------------------------------- */ -class HTTPRequestException : public std::exception { - virtual const char *what(void) const throw() - { - return "HTTPRequest exception occured !"; - } -}; - -/* HTTPRequest class ----------------------------------- */ -class HTTPRequest { - public: - /* Contructors */ - /** - * @breif The HTTPRequest constructor - * - * @details The constructor parses the HTTP request. - * - * @param[in] pMsg The received HTTP request - * - * @throws #HTTPRequestException if parsing fails - */ - HTTPRequest(const std::string &pMsg); - - /* Destructor */ - /** - * @brief The HTTPRequest class destructor - */ - virtual ~HTTPRequest(); - - /* Getters */ - std::string msg(void) const; - std::string methodStr(void) const; - httpMethod_t method(void) const; - std::string httpVersionStr(void) const; - httpVersion_t httpVersion(void) const; - std::string host(void) const; - std::string URL(void) const; - std::string userAgent(void) const; - std::string accept(void) const; - std::string acceptLanguage(void) const; - std::string acceptEncoding(void) const; - std::string referer(void) const; - std::string upgradeInsecureRequest(void) const; - std::string headers(void) const; - std::string URI(void) const; - std::string query(void) const; - httpBody_t body(void) const; - std::string payload(void) const; - - /* Setters */ - /* TODO */ - // void setMsg(const std::string &pMsg); - // void setMethodStr(const std::string &pMsg); - // void setHTTPVersionStr(const std::string &pMsg); - // void setHeaders(const std::string &pMsg); - // void setURI(const std::string &pMsg); - // void setHost(const std::string &pMsg); - // void setURL(const std::string &pMsg); - // void setQuery(const std::string &pMsg); - - protected: - private: - /* Request contents */ - std::string mMsg; /**< Raw message received */ - std::string mMethodStr; /**< HTTP method */ - std::string mHTTPVersionStr; /**< HTTP Version */ - std::string mURL; /**< HTTP URL */ - std::string mHost; /**< HTTP Host */ - std::string mUserAgent; /**< HTTP Client user agent */ - std::string mAccept; /**< HTTP Accept field */ - std::string mAcceptLanguage; /**< HTTP Accept language */ - std::string mAcceptEncoding; /**< HTTP Accept encoding */ - std::string mReferer; /**> HTTP referer */ - std::string mUpgradeInsecureRequest; /**< HTTP UpgradeInsecureRequest flag */ - std::string mHeaders; /**< HTTP Headers */ - std::string mURI; /**< HTTP URI */ - std::string mQuery; /**< HTTP Query */ - httpBody_t mBody; /**< HTTP Body */ - std::string mPayload; /**< HTTP payload */ -}; diff --git a/generator/src/rest/inc/RESTServer.hpp b/generator/src/rest/inc/RESTServer.hpp deleted file mode 100644 index 6744553..0000000 --- a/generator/src/rest/inc/RESTServer.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @brief RESTServer class - * - * @file RESTServer.hpp - */ - -#ifndef RESTSERVER_HPP -#define RESTSERVER_HPP - -/* Includes -------------------------------------------- */ -/* C++ system */ -#include -#include -#include - -/* Defines --------------------------------------------- */ - -/* Type definitions ------------------------------------ */ - -/* Forward declarations -------------------------------- */ - -/* RESTServer exception -------------------------------- */ -class RESTServerException : public std::exception { - virtual const char *what(void) const throw() - { - return "RESTServer exception occured !"; - } -}; - -/* RESTServer class ------------------------------------ */ -class RESTServer { - public: - /* Types */ - /** - * @brief Callback type for the REST API methods. - * - * @details A method callback provides a way to build the response - * to a certain method. - * - * @param[in] pMsg The request. - * @param[out] pOut The output string : the response. - * - * @return Returns true if successful, false elsewise - */ - using methodFct_t = std::function; - - /* Contructors */ - RESTServer(const std::string &pAddr, const std::string pPort, const std::string &pPath); - - /* Destructor */ - /** - * @brief The RESTServer class destructor - */ - virtual ~RESTServer(); - - /* Getters */ - std::string address(void) const; - std::string port(void) const; - std::string apiPath(void) const; - - methodFct_t getCallback(void) const; - methodFct_t postCallback(void) const; - methodFct_t putCallback(void) const; - methodFct_t delCallback(void) const; - - /* Setters */ - void setGetCallback(const methodFct_t &pFct); - void setPostCallback(const methodFct_t &pFct); - void setPutCallback(const methodFct_t &pFct); - void setDelCallback(const methodFct_t &pFct); - - /* Server management */ - bool open(void); - bool listen(void); - bool close(void); - - protected: - private: - /* Request processing functions */ - bool processClientMessage(const char * const pMsg, const size_t &pReadBytes, const int &pClientSocket) const; - // bool processGetRequest(const std::string &pMsg) const; - // bool processPutRequest(const std::string &pMsg) const; - // bool processPostRequest(const std::string &pMsg) const; - // bool processDelRequest(const std::string &pMsg) const; - - /* Networking member variables */ - int mServerSocket; - - std::string mAddr; - std::string mPort; - std::string mPath; - - /* REST API callbacks */ - methodFct_t mGetCallback; /**< REST API GET method callback */ - methodFct_t mPostCallback; /**< REST API POST method callback */ - methodFct_t mPutCallback; /**< REST API PUT method callback */ - methodFct_t mDelCallback; /**< REST API DEL method callback */ -}; - -#endif /* RESTSERVER_HPP */ diff --git a/generator/src/rest/resources/webpage.cpp b/generator/src/rest/resources/webpage.cpp deleted file mode 100644 index b7d7d2a..0000000 --- a/generator/src/rest/resources/webpage.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Let There Be Light project - * - * @file webpage.cpp - */ - -/* Includes -------------------------------------------- */ -#include "webpage.hpp" - -/* Defines --------------------------------------------- */ - -/* Variable declarations ------------------------------- */ -/* Web page variables ---------------------------------- */ -const char * const htmlResponseCode200 = R"=====(HTTP/1.1 200 OK -Content-type:text/html -Connection: close -)====="; - -const char * const htmlResponseCode400 = R"=====(HTTP/1.0 400 BAD REQUEST -Content-Type: text/html -Connection: close - - - - - 400 - BAD REQUEST - - - Your browser sent a bad request, - such as a POST without a Content-Length. - - -)====="; - -const char * const htmlResponseCode404 = R"=====(HTTP/1.0 404 NOT FOUND -Content-Type: text/html -Connection: close - - - - - 404 - Not found - - - The server could not fulfill your request because the resource specified" - is unavailable or nonexistent. -
" - Please check that you entered the correct URL. -
- - -)====="; - -const char * const htmlResponseCode500 = R"=====(HTTP/1.0 500 Server internal error -Content-Type: text/html -Connection: close - - - - - 500 - Server internal error - - - Server-side error prohibited execution. - - -)====="; - -const char * const htmlResponseCode501 = R"=====(HTTP/1.1 501 Method Not Implemented -Content-type:text/html -Connection: close - - - - - - 501 - Method Not Implemented - - - - HTTP request method not supported. - - -)====="; - -const char * const htmlDocType = R"=====( -)====="; - -const char * const htmlPageBegin = R"=====( -)====="; - -const char * const htmlPageEnd = R"=====( - -)====="; - -// CSS to style the on/off buttons -// Feel free to change the background-color and font-size attributes to fit your preferences -const char * const htmlHead = R"=====( - - - - - -)====="; - -const char * const htmlGeneralKenobi = R"=====( - - - web-example - - - - Hello there ! - - General Kenobi ! - - -)====="; diff --git a/generator/src/rest/resources/webpage.hpp b/generator/src/rest/resources/webpage.hpp deleted file mode 100644 index 6723337..0000000 --- a/generator/src/rest/resources/webpage.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Let There Be Light project - * - * @file webpage.hpp - */ -#ifndef INDEX_HPP -#define INDEX_HPP - -/* Includes -------------------------------------------- */ - -/* Defines --------------------------------------------- */ - -/* Forward declarations -------------------------------- */ -class WiFiClient; - -/* Variable declarations ------------------------------- */ -extern const char * const htmlResponseCode200; -extern const char * const htmlResponseCode400; -extern const char * const htmlResponseCode404; -extern const char * const htmlResponseCode500; -extern const char * const htmlResponseCode501; - -extern const char * const htmlDocType; -extern const char * const htmlPageBegin; -extern const char * const htmlPageEnd; -extern const char * const htmlHead; - -extern const char * const htmlGeneralKenobi; - -/* Web pages ------------------------------------------- */ - -#endif /* INDEX_HPP */ diff --git a/generator/src/rest/src/CMakeLists.txt b/generator/src/rest/src/CMakeLists.txt deleted file mode 100644 index 8b1378d..0000000 --- a/generator/src/rest/src/CMakeLists.txt +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright (C) 2020 Clovis Durand -# -# ----------------------------------------------------------------------------- - -# Header files -------------------------------------------- -file(GLOB PUBLIC_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/../inc/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/../inc/*.hpp -) - -file(GLOB RESOURCE_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/../resources/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/../resources/*.hpp -) - -file(GLOB_RECURSE MODULE_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp -) - -set(HEADERS - ${PUBLIC_HEADERS} - ${MODULE_HEADERS} - ${RESOURCE_HEADERS} -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../inc/) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../resources/) - -# Source files -------------------------------------------- -file(GLOB SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/*.c - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp -) - -file(GLOB RESOURCE_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/../resources/*.c - ${CMAKE_CURRENT_SOURCE_DIR}/../resources/*.cpp -) - -list(REMOVE_ITEM SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) - -message("cpprest-api SOURCES : ${SOURCES};${RESOURCE_SOURCES}") - -# Link directories ---------------------------------------- - -# Target definition --------------------------------------- -add_library(cpprest-api SHARED - ${SOURCES} - ${RESOURCE_SOURCES} -) -target_link_libraries(cpprest-api PRIVATE - ${CMAKE_THREAD_LIBS_INIT} -) -set_target_properties(cpprest-api PROPERTIES - PUBLIC_HEADER "${PUBLIC_HEADERS}" -) - -add_executable(cpprest-api-test - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp -) -add_dependencies(cpprest-api-test - cpprest-api -) -target_link_libraries(cpprest-api-test PUBLIC - cpprest-api -) - -#---------------------------------------------------------------------------- -# The installation is prepended by the CMAKE_INSTALL_PREFIX variable -install(TARGETS cpprest-api - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - PUBLIC_HEADER DESTINATION include -) - -install(TARGETS cpprest-api-test - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - PUBLIC_HEADER DESTINATION include -) diff --git a/generator/src/rest/src/HTTPRequest.cpp b/generator/src/rest/src/HTTPRequest.cpp deleted file mode 100644 index e02f91f..0000000 --- a/generator/src/rest/src/HTTPRequest.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @brief HTTPRequest class implementation - * - * @file HTTPRequest.cpp - */ - - -/* Includes -------------------------------------------- */ -#include "HTTPRequest.hpp" - -/* C++ System */ -#include - -/* Defines --------------------------------------------- */ - -/* Type definitions ------------------------------------ */ - -/* Helper functions ------------------------------------ */ -static std::string toStr(const httpVersion_t &pVersion) { - switch(pVersion) { - case HTTP_VERSION_1_0: - return "HTTP/1.0"; - case HTTP_VERSION_1_1: - return "HTTP/1.1"; - case HTTP_VERSION_2_0: - return "HTTP/2.0"; - default: - std::cerr << "[ERROR] toStr Unknown HTTP version = " << pVersion << std::endl; - return ""; - } -} - -static std::string toStr(const httpMethod_t &pMethod) { - switch(pMethod) { - case HTTP_METHOD_GET: - return "GET"; - case HTTP_METHOD_HEAD: - return "HEAD"; - case HTTP_METHOD_POST: - return "POST"; - case HTTP_METHOD_PUT: - return "PUT"; - case HTTP_METHOD_DELETE: - return "DELETE"; - case HTTP_METHOD_CONNECT: - return "CONNECT"; - case HTTP_METHOD_OPTIONS: - return "OPTIONS"; - case HTTP_METHOD_TRACE: - return "TRACE"; - case HTTP_METHOD_PATCH: - return "PATCH"; - default: - std::cerr << "[ERROR] toStr Unknown HTTP method = " << pMethod << std::endl; - return ""; - } -} - -static httpVersion_t strToHTTPVersion(const std::string &pStr) { - if (pStr == toStr(HTTP_VERSION_1_0)) { - return HTTP_VERSION_1_0; - } else if (pStr == toStr(HTTP_VERSION_1_1)) { - return HTTP_VERSION_1_1; - } else if (pStr == toStr(HTTP_VERSION_2_0)) { - return HTTP_VERSION_2_0; - } else { - std::cerr << "[ERROR] Unknown HTTP version = " << pStr << std::endl; - return HTTP_VERSION_UNKNOWN; - } -} - -static httpMethod_t strToHTTPMethod(const std::string &pStr) { - if (pStr == toStr(HTTP_METHOD_GET)) { - return HTTP_METHOD_GET; - } else if (pStr == toStr(HTTP_METHOD_HEAD)) { - return HTTP_METHOD_HEAD; - } else if (pStr == toStr(HTTP_METHOD_POST)) { - return HTTP_METHOD_POST; - } else if (pStr == toStr(HTTP_METHOD_PUT)) { - return HTTP_METHOD_PUT; - } else if (pStr == toStr(HTTP_METHOD_DELETE)) { - return HTTP_METHOD_DELETE; - } else if (pStr == toStr(HTTP_METHOD_TRACE)) { - return HTTP_METHOD_TRACE; - } else if (pStr == toStr(HTTP_METHOD_OPTIONS)) { - return HTTP_METHOD_OPTIONS; - } else if (pStr == toStr(HTTP_METHOD_CONNECT)) { - return HTTP_METHOD_CONNECT; - } else if (pStr == toStr(HTTP_METHOD_PATCH)) { - return HTTP_METHOD_PATCH; - } else { - std::cerr << "[ERROR] Unknown HTTP method = " << pStr << std::endl; - return HTTP_METHOD_UNKNOWN; - } -} - - -/* HTTPRequest class implementation -------------------- */ -HTTPRequest::HTTPRequest(const std::string &pMsg) : - mMsg(pMsg) -{ - /* If the argument is empty, throw exception */ - if(pMsg.empty()) { - std::cerr << "[ERROR] Empty argument" << std::endl; - throw HTTPRequestException(); - } - - /* Get the method */ - size_t lPos1 = 0; - size_t lPos2 = mMsg.find(' '); - std::cout << "[DEBUG] Method : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mMethodStr = mMsg.substr(lPos1, lPos2 - lPos1); - - /* Get the URL */ - lPos1 = lPos2 + 1; - lPos2 = mMsg.find(' ', lPos1); - std::cout << "[DEBUG] URL : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mURL = mMsg.substr(lPos1, lPos2 - lPos1); - - /* Get the HTTP version */ - lPos1 = lPos2 + 1; - lPos2 = mMsg.find('\n', lPos1); - std::cout << "[DEBUG] Host : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mHTTPVersionStr = mMsg.substr(lPos1, lPos2 - lPos1); - - /* Get the host */ - lPos1 = lPos2 + 1; - lPos1 = mMsg.find("Host: ", lPos1) + std::string("Host: ").size(); - lPos2 = mMsg.find('\n', lPos1); - std::cout << "[DEBUG] Host : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mHost = mMsg.substr(lPos1, lPos2 - lPos1); - - /* Get the User-Agent */ - lPos1 = lPos2 + 1; - lPos1 = mMsg.find("User-Agent: ", lPos1) + std::string("User-Agent: ").size(); - lPos2 = mMsg.find('\n', lPos1); - std::cout << "[DEBUG] Host : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mUserAgent = mMsg.substr(lPos1, lPos2 - lPos1); - - /* Get the Accept field */ - lPos1 = lPos2 + 1; - lPos1 = mMsg.find("Accept: ", lPos1) + std::string("Accept: ").size(); - lPos2 = mMsg.find('\n', lPos1); - std::cout << "[DEBUG] Host : lPos1 : " << lPos1 << ", lPos2 : " << lPos2 << std::endl; - mAccept = mMsg.substr(lPos1, lPos2 - lPos1); -} - -HTTPRequest::~HTTPRequest() { - /* Empty */ -} - -/* Getters */ -std::string HTTPRequest::msg(void) const { - return mMsg; -} - -std::string HTTPRequest::methodStr(void) const { - return mMethodStr; -} - -httpMethod_t HTTPRequest::method(void) const { - return strToHTTPMethod(mMethodStr); -} - -std::string HTTPRequest::httpVersionStr(void) const { - return mHTTPVersionStr; -} - -httpVersion_t HTTPRequest::httpVersion(void) const { - return strToHTTPVersion(mHTTPVersionStr); -} - -std::string HTTPRequest::URL(void) const { - return mURL; -} - -std::string HTTPRequest::host(void) const { - return mHost; -} - -std::string HTTPRequest::userAgent(void) const { - return mUserAgent; -} - -std::string HTTPRequest::accept(void) const { - return mAccept; -} - -std::string HTTPRequest::acceptLanguage(void) const { - return mAcceptLanguage; -} - -std::string HTTPRequest::acceptEncoding(void) const { - return mAcceptEncoding; -} - -std::string HTTPRequest::referer(void) const { - return mReferer; -} - -std::string HTTPRequest::upgradeInsecureRequest(void) const { - return mUpgradeInsecureRequest; -} - - -std::string HTTPRequest::headers(void) const { - return mHeaders; -} - -std::string HTTPRequest::URI(void) const { - return mURI; -} - -std::string HTTPRequest::query(void) const { - return mQuery; -} - -httpBody_t HTTPRequest::body(void) const { - return mBody; -} - -std::string HTTPRequest::payload(void) const { - return mPayload; -} - -/* Setters */ diff --git a/generator/src/rest/src/RESTServer.cpp b/generator/src/rest/src/RESTServer.cpp deleted file mode 100644 index f4b172e..0000000 --- a/generator/src/rest/src/RESTServer.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/** - * @brief RESTServer class implementation - * - * @file RESTServer.cpp - */ - -/* Includes -------------------------------------------- */ -#include "RESTServer.hpp" -#include "HTTPRequest.hpp" - -#include "webpage.hpp" - -/* C++ system */ -#include - -/* C errno */ -#include -#include -#include - -/* C Network */ -#include /* socket */ -#include /* sockaddr_in */ -#include /* close */ - -/* Defines --------------------------------------------- */ -#define SERVER_BUFFER_SIZE 4096U - -/* Type definitions ------------------------------------ */ - -/* Forward declarations -------------------------------- */ - -/* Helper functions ------------------------------------ */ - -/* RESTServer class implementation --------------------- */ -/* Contructors */ -RESTServer::RESTServer(const std::string &pAddr, const std::string pPort, const std::string &pPath) : - mAddr(pAddr), - mPort(pPort), - mPath(pPath) -{ - /* Empty */ -} - -/* Destructor */ -RESTServer::~RESTServer() { - /* Empty */ -} - -/* Getters */ -std::string RESTServer::address(void) const { - return mAddr; -} - -std::string RESTServer::port(void) const { - return mPort; -} - -std::string RESTServer::apiPath(void) const { - return mPath; -} - -RESTServer::methodFct_t RESTServer::getCallback(void) const { - return mGetCallback; -} - -RESTServer::methodFct_t RESTServer::postCallback(void) const { - return mPostCallback; -} - -RESTServer::methodFct_t RESTServer::putCallback(void) const { - return mPutCallback; -} - -RESTServer::methodFct_t RESTServer::delCallback(void) const { - return mDelCallback; -} - -/* Setters */ -void RESTServer::setGetCallback(const methodFct_t &pFct) { - mGetCallback = pFct; -} - -void RESTServer::setPostCallback(const methodFct_t &pFct) { - mPostCallback = pFct; -} - -void RESTServer::setPutCallback(const methodFct_t &pFct) { - mPutCallback = pFct; -} - -void RESTServer::setDelCallback(const methodFct_t &pFct) { - mDelCallback = pFct; -} - -/* Server management */ -bool RESTServer::open(void) { - /* Create a socket */ - errno = 0; - int lSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if(0 > mServerSocket) { - std::cerr << "[ERROR] Failed to create socket" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - - /* Set the socket member variable */ - mServerSocket = lSocket; - - /* Initialisation de la structure sockaddr_in */ - struct sockaddr_in lServerAddrIn; - std::memset(&lServerAddrIn, 0, sizeof(struct sockaddr_in)); - /* Socket type */ - lServerAddrIn.sin_family = AF_INET; - /* Accpeted client IP addresses */ - lServerAddrIn.sin_addr.s_addr = INADDR_ANY; - /* Port */ - lServerAddrIn.sin_port = htons(std::atoi(mPort.c_str())); - - /* Set socket options */ - errno = 0; - const int lEnableOption = 1; - if(0 > setsockopt(mServerSocket, SOL_SOCKET, SO_REUSEADDR, (const void *)&lEnableOption, sizeof(lEnableOption))) { - std::cerr << "[ERROR] setsockopt SO_REUSEADDR failed" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - if(0 > setsockopt(mServerSocket, SOL_SOCKET, SO_REUSEPORT, (const void *)&lEnableOption, sizeof(lEnableOption))) { - std::cerr << "[ERROR] setsockopt SO_REUSEPORT failed" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - - /* Bind socket */ - errno = 0; - if(0 > bind(mServerSocket, (const struct sockaddr *)&lServerAddrIn , sizeof(lServerAddrIn))) { - std::cerr << "[ERROR] Failed to bind socket" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - - return true; -} - -bool RESTServer::listen(void) { - /* Listen for connections */ - errno = 0; - if(0 > ::listen(mServerSocket, 32)) { - std::cerr << "[ERROR] Failed to listen for new connections" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - - /* Set up before listening in */ - int lClientSock = 0; - struct sockaddr_in lClientAddrIn; - std::memset(&lClientAddrIn, 0, sizeof(struct sockaddr_in)); - socklen_t lsInSize = sizeof(lClientAddrIn); - char lClientMsg[SERVER_BUFFER_SIZE]; - - /* Start listening loop */ - while((lClientSock = accept(mServerSocket, (struct sockaddr *)&lClientAddrIn, &lsInSize))) { - /* Check if the client is valid */ - if(0 <= lClientSock) { - /* Read the contents of the message */ - size_t lReadBytes = 0; - while(0 < (lReadBytes = recv(lClientSock, lClientMsg, SERVER_BUFFER_SIZE, 0))) { - /* Process the message */ - std::cout << "[DEBUG] Got message : " << std::endl - << lClientMsg << std::endl; - - if(processClientMessage(lClientMsg, lReadBytes, lClientSock)) { - break; /* TODO : Manage error cases */ - } - } - - /* Close the client's socket */ - errno = 0; - if(0 > ::close(lClientSock)) { - std::cerr << "[ERROR] Failed to close client socket" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - } else { - std::cerr << "[ERROR] Failed to accept client connection" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - } - - return true; -} - -bool RESTServer::close(void) { - errno = 0; - if(0 > ::close(mServerSocket)) { - std::cerr << "[ERROR] Failed to close socket" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - return false; - } - - return true; -} - -bool RESTServer::processClientMessage(const char * const pMsg, const size_t &pReadBytes, const int &pClientSocket) const { - (void)pReadBytes; - - if(nullptr == pMsg) { - std::cerr << "[DEBUG] pMsg arg is nullptr" << std::endl; - return false; - } - - /* Set a httpMessage_t var for the HTTP Parser */ - HTTPRequest *lHTTPRequest = nullptr; - try { - lHTTPRequest = new HTTPRequest((std::string(pMsg))); - } catch (const std::exception &e) { - std::cerr << "[ERROR] Failed to parse the HTTPRequest" << std::endl; - return false; - } - - /* For debug purposes, print everything */ - std::cout << "[DEBUG] HTTPRequest contents : " << std::endl - << " Raw : " << std::endl << lHTTPRequest->msg() << std::endl - << " Method : " << lHTTPRequest->methodStr() << std::endl - << " URL : " << lHTTPRequest->URL() << std::endl - << " HTTPV : " << lHTTPRequest->httpVersionStr() << std::endl - << " Host : " << lHTTPRequest->host() << std::endl - << " User-Agent : " << lHTTPRequest->userAgent() << std::endl - << " Accept : " << lHTTPRequest->accept() << std::endl - ; - - int lSentBytes = 0; - std::string lResponse = ""; - switch(lHTTPRequest->method()) { - case HTTP_METHOD_GET: - std::cout << "[DEBUG] Got GET request from client" << std::endl; - - /* Build response */ - lResponse = std::string(htmlResponseCode200) + "\r\n"; - getCallback()("{\"ACK\": true}\r\n", lResponse); - - lSentBytes = send(pClientSocket, lResponse.c_str(), std::strlen(lResponse.c_str()), 0); - if(0 > lSentBytes) { - std::cerr << "[ERROR] Failed to send a response to the client" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - - delete lHTTPRequest; - - return false; - } else { - std::cout << "[DEBUG] Sent " << lSentBytes << " bytes as a response" << std::endl; - } - break; - default: - std::cerr << "[ERROR] Got unsupported HTTP method request : " << lHTTPRequest->methodStr() << std::endl; - - lSentBytes = send(pClientSocket, htmlResponseCode501, std::strlen(htmlResponseCode501), 0); - if(0 > lSentBytes) { - std::cerr << "[ERROR] Failed to send a response to the client" << std::endl; - if(0 != errno) { - std::cerr << " errno = " << errno << " (" << strerror(errno) << ")" << std::endl; - } - } else { - std::cout << "[DEBUG] Sent " << lSentBytes << " bytes as a response" << std::endl; - } - - delete lHTTPRequest; - - return false; - } - - delete lHTTPRequest; - - return true; -} diff --git a/generator/src/rest/src/main.cpp b/generator/src/rest/src/main.cpp deleted file mode 100644 index ca328ab..0000000 --- a/generator/src/rest/src/main.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @brief C++ REST API test main source file - * - * @file main.cpp - */ - -/* Includes -------------------------------------------- */ -#include "RESTServer.hpp" - -/* C++ system */ -#include -#include - -/* C system */ -#include - -/* Defines --------------------------------------------- */ -#define ADDRESS "localhost" - -/* Notes ----------------------------------------------- */ - -/* Variable declaration -------------------------------- */ -std::unique_ptr gRESTServer; - -/* Type definitions ------------------------------------ */ - -/* Support functions ----------------------------------- */ -static void printUsage(const char * const pProgName) -{ - std::cout << "[USAGE] %s" << pProgName << std::endl; - std::cout << " : Localhost port number" << std::endl; -} - -/* REST Test callbacks */ -static RESTServer::methodFct_t sGetCallback = [](const std::string &pMsg, std::string &pOut) -> bool { - (void)pMsg; - - pOut += "{\"ACK\": true}\r\n"; - - return true; -}; - -/* ----------------------------------------------------- */ -/* Main tests ------------------------------------------ */ -/* ----------------------------------------------------- */ -int main(const int argc, const char * const * const argv) { - if ((argc < 2) || (std::strcmp(argv[1U], "--help") == 0)) { - printUsage(argv[0]); - return EXIT_FAILURE; - } - - std::string lAddr = ADDRESS; - std::string lPort = std::string(argv[1U]); - std::string lPath = "OSCO-OD-Gen/Action"; - - /* Create server */ - gRESTServer = std::unique_ptr(new RESTServer(lAddr, lPort, lPath)); - - /* Set REST API callbacks */ - gRESTServer->setGetCallback(sGetCallback); - - /* Open server */ - if(!gRESTServer->open()) { - return EXIT_FAILURE; - } - - std::cout << "[INFO] Listening for request at: " << lAddr << ":" << lPort << "/" << lPath << std::endl; - - /* Main loop */ - gRESTServer->listen(); - - /* Close server */ - if(!gRESTServer->close()) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -}