diff --git a/webserv/config/validation/directive_rules/CgiExtValidationRule.cpp b/webserv/config/validation/directive_rules/CgiExtValidationRule.cpp index 1ead6b9..aa51512 100644 --- a/webserv/config/validation/directive_rules/CgiExtValidationRule.cpp +++ b/webserv/config/validation/directive_rules/CgiExtValidationRule.cpp @@ -17,7 +17,7 @@ CgiExtValidationRule::CgiExtValidationRule(bool requiresValue) bool isAllowedCGIExtension(const std::string &extension) { - static const std::vector allowedExtensions = {".php", ".py", ".bla", ".sh", ".cgi"}; + static const std::vector allowedExtensions = {".php", ".py", ".bla", ".cgi", ".sh"}; return std::ranges::any_of(allowedExtensions, [&extension](const auto &it) { return extension == it; }); } diff --git a/webserv/handler/CgiEnvironment.cpp b/webserv/handler/CgiEnvironment.cpp index 6e60d6f..6b05d31 100644 --- a/webserv/handler/CgiEnvironment.cpp +++ b/webserv/handler/CgiEnvironment.cpp @@ -1,14 +1,19 @@ -#include +#include "webserv/http/HttpRequest.hpp" +#include "webserv/log/Log.hpp" +#include #include // for URI #include // for HttpHeaders +#include +#include #include // for strcpy, size_t #include // for optional #include // for pair CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request) { + Log::trace(LOCATION); env_["GATEWAY_INTERFACE"] = "CGI/1.1"; env_["SERVER_PROTOCOL"] = "HTTP/1.1"; env_["REQUEST_METHOD"] = request.getMethod(); @@ -38,7 +43,7 @@ CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request) env_["SERVER_NAME"] = host; env_["SERVER_PORT"] = std::to_string(port); env_["REMOTE_ADDR"] = request.getClient().getClientAddress(); // Placeholder, should be set to actual remote address - env_["REDIRECT_STATUS"] = "200"; // Required by PHP with force-cgi-redirect enabled + env_["REDIRECT_STATUS"] = "200"; // Required by PHP with force-cgi-redirect enabled env_["SERVER_SOFTWARE"] = "Webserv/1.0"; env_["REQUEST_SCHEME"] = "HTTP"; env_["HTTP_VERSION"] = "1.1"; @@ -49,6 +54,8 @@ CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request) env_["HTTP_ACCEPT"] = headers.get("Accept"); env_["HTTP_ACCEPT_LANGUAGE"] = headers.get("Accept-Language"); env_["HTTP_ACCEPT_ENCODING"] = headers.get("Accept-Encoding"); + + appendCustomHeaders(headers); } char **CgiEnvironment::toEnvp() const @@ -63,4 +70,21 @@ char **CgiEnvironment::toEnvp() const } envp[index] = nullptr; // Null-terminate the array return envp; +} + +void CgiEnvironment::appendCustomHeaders(const HttpHeaders &headers) +{ + Log::trace(LOCATION); + for (const auto &header : headers.getAll()) + { + if (!header.first.starts_with("x-")) + { + continue; + } + std::string key = "HTTP_" + header.first; + std::transform(key.begin(), key.end(), key.begin(), ::toupper); + std::replace(key.begin(), key.end(), '-', '_'); + env_[key] = header.second; + Log::debug("Added custom header with key: " + key + " And value: " + header.second); + } } \ No newline at end of file diff --git a/webserv/handler/CgiEnvironment.hpp b/webserv/handler/CgiEnvironment.hpp index 897a559..05c462f 100644 --- a/webserv/handler/CgiEnvironment.hpp +++ b/webserv/handler/CgiEnvironment.hpp @@ -18,5 +18,6 @@ class CgiEnvironment [[nodiscard]] char **toEnvp() const; private: + void appendCustomHeaders(const HttpHeaders &headers); std::map env_; }; diff --git a/webserv/handler/CgiHandler.cpp b/webserv/handler/CgiHandler.cpp index f88cfa0..78da490 100644 --- a/webserv/handler/CgiHandler.cpp +++ b/webserv/handler/CgiHandler.cpp @@ -1,6 +1,5 @@ -#include - #include // for Client +#include #include // for CgiProcess #include // for ErrorHandler #include // for HttpRequest @@ -11,6 +10,8 @@ #include // for trim #include +#include +#include #include // for function #include // for move @@ -268,7 +269,16 @@ void CgiHandler::parseCgiBody() { Log::trace(LOCATION); - // Append the body to the response + auto status = response_.getHeaders().get("Status"); + + if (cgiProcess_->getExitCode() > 0 && !status.empty()) + { + response_.setStatus(500); + } + else if (!status.empty()) + { + response_.setStatus(std::atoi(status.c_str())); + } response_.appendBody(buffer_); response_.setComplete(); buffer_.clear(); diff --git a/webserv/handler/CgiProcess.cpp b/webserv/handler/CgiProcess.cpp index 33edab4..159b139 100644 --- a/webserv/handler/CgiProcess.cpp +++ b/webserv/handler/CgiProcess.cpp @@ -1,7 +1,6 @@ -#include - #include // for CgiEnvironment #include // for CgiHandler +#include #include // for URI #include // for HttpRequest #include // for Log @@ -19,7 +18,7 @@ #include // for waitpid, WNOHANG #include // for close, dup2, pipe2, execve, fork, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO -CgiProcess::CgiProcess(const HttpRequest &request, CgiHandler &handler) : request_(request), handler_(handler), _pid(-1) +CgiProcess::CgiProcess(const HttpRequest &request, CgiHandler &handler) : request_(request), handler_(handler), pid_(-1), status_(-1) { if (!request_.getUri().isCgi()) { @@ -49,8 +48,8 @@ void CgiProcess::spawn() } // NOLINTEND CgiEnvironment cgiEnv(uri, request_); - _pid = fork(); - if (_pid < 0) + pid_ = fork(); + if (pid_ < 0) { close(pipeStdin[0]); close(pipeStdin[1]); @@ -60,7 +59,7 @@ void CgiProcess::spawn() close(pipeStderr[1]); throw std::runtime_error("Failed to fork"); } - if (_pid == 0) + if (pid_ == 0) { dup2(pipeStdin[0], STDIN_FILENO); dup2(pipeStdout[1], STDOUT_FILENO); @@ -98,34 +97,34 @@ void CgiProcess::spawn() close(pipeStdout[1]); close(pipeStderr[1]); - Log::debug("CGI process forked with PID: " + std::to_string(_pid)); + Log::debug("CGI process forked with PID: " + std::to_string(pid_)); // request_.getClient().setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); // move the sockets to the // client handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut), std::move(cgiStdErr)); - handler_.setPid(_pid); + handler_.setPid(pid_); } } void CgiProcess::kill() const noexcept { - if (_pid > 0) + if (pid_ > 0) { - ::kill(_pid, SIGKILL); - Log::debug("Killed CGI process with PID: " + std::to_string(_pid)); + ::kill(pid_, SIGKILL); + Log::debug("Killed CGI process with PID: " + std::to_string(pid_)); } } void CgiProcess::wait() noexcept { - if (_pid > 0) + if (pid_ > 0) { int status; - int waitResult = ::waitpid(_pid, &status, WNOHANG); + int waitResult = ::waitpid(pid_, &status, WNOHANG); if (waitResult == -1) { - Log::error("Error while waiting for CGI process with PID: " + std::to_string(_pid)); + Log::error("Error while waiting for CGI process with PID: " + std::to_string(pid_)); return; } if (waitResult == 0) @@ -134,8 +133,13 @@ void CgiProcess::wait() noexcept return; } - Log::debug("CGI process with PID " + std::to_string(_pid) + " has terminated"); - ; - _pid = -1; + Log::debug("CGI process with PID " + std::to_string(pid_) + " has terminated with status " + std::to_string(status)); + status_ = status; + pid_ = -1; } +} + +int CgiProcess::getExitCode() const noexcept +{ + return status_; } \ No newline at end of file diff --git a/webserv/handler/CgiProcess.hpp b/webserv/handler/CgiProcess.hpp index 68221f1..655408b 100644 --- a/webserv/handler/CgiProcess.hpp +++ b/webserv/handler/CgiProcess.hpp @@ -20,11 +20,14 @@ class CgiProcess void kill() const noexcept; void wait() noexcept; + [[nodiscard]] int getExitCode() const noexcept; + private: const HttpRequest &request_; CgiHandler &handler_; - int _pid; + int pid_; + int status_; // int _cgiFd; void spawn(); diff --git a/webserv/http/HttpHeaders.cpp b/webserv/http/HttpHeaders.cpp index 766fbc5..2e754e8 100644 --- a/webserv/http/HttpHeaders.cpp +++ b/webserv/http/HttpHeaders.cpp @@ -1,12 +1,13 @@ -#include // for HttpHeaders - #include // for CRLF +#include // for HttpHeaders #include #include // for trim #include // for __transform_fn, transform #include // for tolower -#include // for pair +#include +#include +#include // for pair std::optional HttpHeaders::getContentLength() const { @@ -94,6 +95,11 @@ void HttpHeaders::parse(const std::string &rawHeaders) noexcept } } +const std::unordered_map &HttpHeaders::getAll() const noexcept +{ + return headers_; +} + std::string HttpHeaders::toString() const noexcept { std::string result; diff --git a/webserv/http/HttpHeaders.hpp b/webserv/http/HttpHeaders.hpp index 63e8bd8..747aa4d 100644 --- a/webserv/http/HttpHeaders.hpp +++ b/webserv/http/HttpHeaders.hpp @@ -29,6 +29,7 @@ class HttpHeaders [[nodiscard]] std::optional getContentLength() const; [[nodiscard]] std::optional getContentType() const noexcept; [[nodiscard]] std::optional getHost() const noexcept; + [[nodiscard]] const std::unordered_map &getAll() const noexcept; private: std::unordered_map headers_;