diff options
author | Roland Reichwein <mail@reichwein.it> | 2023-01-12 20:00:40 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2023-01-12 20:00:40 +0100 |
commit | 702d32b41c1c4f496dba046c2017cb5b907e55cd (patch) | |
tree | 271a48cc1dc9ef1d2fcc846ed4bebbcdd24242e2 /tests/fcgi1.cpp | |
parent | 124646fe2a31b7211d12fb043fcb760cbe7313b0 (diff) |
FCGI test
Diffstat (limited to 'tests/fcgi1.cpp')
-rw-r--r-- | tests/fcgi1.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/tests/fcgi1.cpp b/tests/fcgi1.cpp new file mode 100644 index 0000000..f7d2837 --- /dev/null +++ b/tests/fcgi1.cpp @@ -0,0 +1,89 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <dirent.h> +#include <sys/types.h> + +#include <fcgiapp.h> + +#include <chrono> +#include <iostream> +#include <functional> +#include <filesystem> +#include <mutex> +#include <regex> +#include <string> +#include <thread> +#include <unordered_map> + +#include <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/property_tree/xml_parser.hpp> + +#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<int>(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; +} + |