diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CGIScript.cpp | 48 | ||||
-rw-r--r-- | src/CGIScript.h | 19 | ||||
-rw-r--r-- | src/main.cpp | 34 |
3 files changed, 71 insertions, 30 deletions
diff --git a/src/CGIScript.cpp b/src/CGIScript.cpp new file mode 100644 index 0000000..2394d31 --- /dev/null +++ b/src/CGIScript.cpp @@ -0,0 +1,48 @@ +#include "CGIScript.h" + +#include <cstdlib> +#include <string> +#include <sstream> + +CGIScript::CGIScript(const std::string& path, const HttpRequest& request) +{ + setenv("CONTENT_LENGTH", "0", true); + setenv("REQUEST_URI", request.uri().c_str(), true); + setenv("SCRIPT_NAME", path.c_str(), true); + setenv("SCRIPT_FILENAME", path.c_str(), true); + setenv("REQUEST_METHOD", "GET", true); + setenv("SERVER_PROTOCOL", "HTTP/1.1", true); + setenv("SERVER_SOFTWARE", "cfws/1.0-dev", true); + + m_pipe = popen(path.c_str(), "r"); + if (!m_pipe) { + perror("cfws: popen"); + return; + } + + m_is_open = true; +} + +CGIScript::~CGIScript() +{ + pclose(m_pipe); + + unsetenv("CONTENT_LENGTH"); + unsetenv("REQUEST_URI"); + unsetenv("SCRIPT_NAME"); + unsetenv("SCRIPT_FILENAME"); + unsetenv("REQUEST_METHOD"); + unsetenv("SERVER_PROTOCOL"); + unsetenv("SERVER_SOFTWARE"); +} + +std::string CGIScript::read_output() +{ + std::stringstream sstream; + + char ch; + while ((ch = fgetc(m_pipe)) != EOF) + sstream << ch; + + return sstream.str(); +} diff --git a/src/CGIScript.h b/src/CGIScript.h new file mode 100644 index 0000000..6e8e031 --- /dev/null +++ b/src/CGIScript.h @@ -0,0 +1,19 @@ +#pragma once + +#include <cstdio> +#include <string> + +#include "HttpRequest.h" + +class CGIScript { +public: + CGIScript(const std::string& path, const HttpRequest&); + ~CGIScript(); + + bool is_open() const { return m_is_open; } + + std::string read_output(); +private: + FILE* m_pipe; + bool m_is_open{false}; +}; diff --git a/src/main.cpp b/src/main.cpp index 4eb90bd..410cb19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include <filesystem> #include <fstream> +#include "CGIScript.h" #include "ClientConnection.h" #include "HttpRequest.h" #include "HttpResponse.h" @@ -54,43 +55,16 @@ static HttpResponse serve_from_cgi(const std::string& executable_path, HttpReque HttpResponse response; response.add_header("Server", "cfws"); - setenv("CONTENT_LENGTH", "0", true); - setenv("REQUEST_URI", request.uri().c_str(), true); - setenv("SCRIPT_NAME", executable_path.c_str(), true); - setenv("SCRIPT_FILENAME", executable_path.c_str(), true); - setenv("REQUEST_METHOD", "GET", true); - setenv("SERVER_PROTOCOL", "HTTP/1.1", true); - setenv("SERVER_SOFTWARE", "cfws/1.0-dev", true); - - std::stringstream sstream; - - FILE* fp = popen(executable_path.c_str(), "r"); - if (!fp) { - perror("cfws: popen"); + CGIScript script(executable_path, request); + if (!script.is_open()) { response.set_status_code(HttpStatusCode::InternalServerError); response.add_header("Content-Type", "text/plain"); response.set_content("Failed to open CGI executable!"); return response; } - char ch; - while ((ch = fgetc(fp)) != EOF) - sstream << ch; - - pclose(fp); - - unsetenv("CONTENT_LENGTH"); - unsetenv("REQUEST_URI"); - unsetenv("SCRIPT_NAME"); - unsetenv("SCRIPT_FILENAME"); - unsetenv("REQUEST_METHOD"); - unsetenv("SERVER_PROTOCOL"); - unsetenv("SERVER_SOFTWARE"); - - // TODO: We should be able to construct a repsonse from an entire string - // instead of always needing to individually set headers and content. response.set_status_code(HttpStatusCode::OK); - response.add_headers_and_content(sstream.str()); + response.add_headers_and_content(script.read_output()); return response; } |