#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" namespace pt = boost::property_tree; using namespace std::string_literals; namespace fs = std::filesystem; // the actual main() for testability int main(int argc, char* argv[]) { int result = FCGX_Init(); if (result != 0) { // error on init fprintf(stderr, "Error: FCGX_Init()\n"); return 1; } result = FCGX_IsCGI(); if (result) { fprintf(stderr, "Error: No FCGI environment available.\n"); return 1; } FCGX_Request request; result = FCGX_InitRequest(&request, 0, 0); if (result != 0) { fprintf(stderr, "Error: FCGX_InitRequest()\n"); return 1; } std::cout << "FGCI app running. Accepting connections." << std::endl; while (FCGX_Accept_r(&request) >= 0) { try { char* method = FCGX_GetParam("REQUEST_METHOD", request.envp); // POST for server actions, changes if (!strcmp(method, "POST") ||!strcmp(method, "GET") ) { size_t contentLength { std::stoul(FCGX_GetParam("CONTENT_LENGTH", request.envp)) }; std::string postData(contentLength, '\0'); // contentLength number of bytes, initialize with 0 if (FCGX_GetStr(postData.data(), contentLength, request.in) != static_cast(contentLength)) { throw std::runtime_error("Bad data read: Content length mismatch.\r\n"); } // postData contains POST data std::string contentType(FCGX_GetParam("CONTENT_TYPE", request.envp)); postData = "returning data of " + contentType + ": " + postData; FCGX_PutS("Content-Type: text/plain\r\n", request.out); FCGX_FPrintF(request.out, "Content-Length: %d\r\n\r\n", postData.size()); FCGX_PutStr(postData.c_str(), postData.size(), request.out); } else { throw std::runtime_error("Unsupported method.\r\n"); } } catch (const std::runtime_error& ex) { FCGX_PutS("Status: 500 Internal Server Error\r\n", request.out); FCGX_PutS("Content-Type: text/html\r\n\r\n", request.out); FCGX_FPrintF(request.out, "Error: %s\r\n", ex.what()); } catch (const std::exception& ex) { FCGX_PutS("Status: 500 Internal Server Error\r\n", request.out); FCGX_PutS("Content-Type: text/html\r\n\r\n", request.out); FCGX_FPrintF(request.out, "Unknown exception: %s\r\n", ex.what()); } } std::cout << "FGCI app exiting." << std::endl; return 0; }