summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CGIScript.cpp48
-rw-r--r--src/CGIScript.h19
-rw-r--r--src/main.cpp34
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;
}