feat: better status hanlding cgi and custom env
This commit is contained in:
parent
c2bdbeb307
commit
6d3941ddf2
@ -17,7 +17,7 @@ CgiExtValidationRule::CgiExtValidationRule(bool requiresValue)
|
|||||||
|
|
||||||
bool isAllowedCGIExtension(const std::string &extension)
|
bool isAllowedCGIExtension(const std::string &extension)
|
||||||
{
|
{
|
||||||
static const std::vector<std::string> allowedExtensions = {".php", ".py", ".bla", ".sh", ".cgi"};
|
static const std::vector<std::string> allowedExtensions = {".php", ".py", ".bla", ".cgi", ".sh"};
|
||||||
return std::ranges::any_of(allowedExtensions, [&extension](const auto &it) { return extension == it; });
|
return std::ranges::any_of(allowedExtensions, [&extension](const auto &it) { return extension == it; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,19 @@
|
|||||||
#include <webserv/handler/CgiEnvironment.hpp>
|
#include "webserv/http/HttpRequest.hpp"
|
||||||
|
#include "webserv/log/Log.hpp"
|
||||||
|
|
||||||
|
#include <webserv/handler/CgiEnvironment.hpp>
|
||||||
#include <webserv/handler/URI.hpp> // for URI
|
#include <webserv/handler/URI.hpp> // for URI
|
||||||
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <cstring> // for strcpy, size_t
|
#include <cstring> // for strcpy, size_t
|
||||||
#include <optional> // for optional
|
#include <optional> // for optional
|
||||||
#include <utility> // for pair
|
#include <utility> // for pair
|
||||||
|
|
||||||
CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request)
|
CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request)
|
||||||
{
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
env_["GATEWAY_INTERFACE"] = "CGI/1.1";
|
env_["GATEWAY_INTERFACE"] = "CGI/1.1";
|
||||||
env_["SERVER_PROTOCOL"] = "HTTP/1.1";
|
env_["SERVER_PROTOCOL"] = "HTTP/1.1";
|
||||||
env_["REQUEST_METHOD"] = request.getMethod();
|
env_["REQUEST_METHOD"] = request.getMethod();
|
||||||
@ -38,7 +43,7 @@ CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request)
|
|||||||
env_["SERVER_NAME"] = host;
|
env_["SERVER_NAME"] = host;
|
||||||
env_["SERVER_PORT"] = std::to_string(port);
|
env_["SERVER_PORT"] = std::to_string(port);
|
||||||
env_["REMOTE_ADDR"] = request.getClient().getClientAddress(); // Placeholder, should be set to actual remote address
|
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_["SERVER_SOFTWARE"] = "Webserv/1.0";
|
||||||
env_["REQUEST_SCHEME"] = "HTTP";
|
env_["REQUEST_SCHEME"] = "HTTP";
|
||||||
env_["HTTP_VERSION"] = "1.1";
|
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"] = headers.get("Accept");
|
||||||
env_["HTTP_ACCEPT_LANGUAGE"] = headers.get("Accept-Language");
|
env_["HTTP_ACCEPT_LANGUAGE"] = headers.get("Accept-Language");
|
||||||
env_["HTTP_ACCEPT_ENCODING"] = headers.get("Accept-Encoding");
|
env_["HTTP_ACCEPT_ENCODING"] = headers.get("Accept-Encoding");
|
||||||
|
|
||||||
|
appendCustomHeaders(headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
char **CgiEnvironment::toEnvp() const
|
char **CgiEnvironment::toEnvp() const
|
||||||
@ -64,3 +71,20 @@ char **CgiEnvironment::toEnvp() const
|
|||||||
envp[index] = nullptr; // Null-terminate the array
|
envp[index] = nullptr; // Null-terminate the array
|
||||||
return envp;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,5 +18,6 @@ class CgiEnvironment
|
|||||||
[[nodiscard]] char **toEnvp() const;
|
[[nodiscard]] char **toEnvp() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void appendCustomHeaders(const HttpHeaders &headers);
|
||||||
std::map<std::string, std::string> env_;
|
std::map<std::string, std::string> env_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#include <webserv/handler/CgiHandler.hpp>
|
|
||||||
|
|
||||||
#include <webserv/client/Client.hpp> // for Client
|
#include <webserv/client/Client.hpp> // for Client
|
||||||
|
#include <webserv/handler/CgiHandler.hpp>
|
||||||
#include <webserv/handler/CgiProcess.hpp> // for CgiProcess
|
#include <webserv/handler/CgiProcess.hpp> // for CgiProcess
|
||||||
#include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler
|
#include <webserv/handler/ErrorHandler.hpp> // for ErrorHandler
|
||||||
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
||||||
@ -11,6 +10,8 @@
|
|||||||
#include <webserv/utils/utils.hpp> // for trim
|
#include <webserv/utils/utils.hpp> // for trim
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
|
|
||||||
@ -268,7 +269,16 @@ void CgiHandler::parseCgiBody()
|
|||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
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_.appendBody(buffer_);
|
||||||
response_.setComplete();
|
response_.setComplete();
|
||||||
buffer_.clear();
|
buffer_.clear();
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#include <webserv/handler/CgiProcess.hpp>
|
|
||||||
|
|
||||||
#include <webserv/handler/CgiEnvironment.hpp> // for CgiEnvironment
|
#include <webserv/handler/CgiEnvironment.hpp> // for CgiEnvironment
|
||||||
#include <webserv/handler/CgiHandler.hpp> // for CgiHandler
|
#include <webserv/handler/CgiHandler.hpp> // for CgiHandler
|
||||||
|
#include <webserv/handler/CgiProcess.hpp>
|
||||||
#include <webserv/handler/URI.hpp> // for URI
|
#include <webserv/handler/URI.hpp> // for URI
|
||||||
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
||||||
#include <webserv/log/Log.hpp> // for Log
|
#include <webserv/log/Log.hpp> // for Log
|
||||||
@ -19,7 +18,7 @@
|
|||||||
#include <sys/wait.h> // for waitpid, WNOHANG
|
#include <sys/wait.h> // for waitpid, WNOHANG
|
||||||
#include <unistd.h> // for close, dup2, pipe2, execve, fork, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO
|
#include <unistd.h> // 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())
|
if (!request_.getUri().isCgi())
|
||||||
{
|
{
|
||||||
@ -49,8 +48,8 @@ void CgiProcess::spawn()
|
|||||||
}
|
}
|
||||||
// NOLINTEND
|
// NOLINTEND
|
||||||
CgiEnvironment cgiEnv(uri, request_);
|
CgiEnvironment cgiEnv(uri, request_);
|
||||||
_pid = fork();
|
pid_ = fork();
|
||||||
if (_pid < 0)
|
if (pid_ < 0)
|
||||||
{
|
{
|
||||||
close(pipeStdin[0]);
|
close(pipeStdin[0]);
|
||||||
close(pipeStdin[1]);
|
close(pipeStdin[1]);
|
||||||
@ -60,7 +59,7 @@ void CgiProcess::spawn()
|
|||||||
close(pipeStderr[1]);
|
close(pipeStderr[1]);
|
||||||
throw std::runtime_error("Failed to fork");
|
throw std::runtime_error("Failed to fork");
|
||||||
}
|
}
|
||||||
if (_pid == 0)
|
if (pid_ == 0)
|
||||||
{
|
{
|
||||||
dup2(pipeStdin[0], STDIN_FILENO);
|
dup2(pipeStdin[0], STDIN_FILENO);
|
||||||
dup2(pipeStdout[1], STDOUT_FILENO);
|
dup2(pipeStdout[1], STDOUT_FILENO);
|
||||||
@ -98,34 +97,34 @@ void CgiProcess::spawn()
|
|||||||
close(pipeStdout[1]);
|
close(pipeStdout[1]);
|
||||||
close(pipeStderr[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
|
// request_.getClient().setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); // move the sockets to the
|
||||||
// client
|
// client
|
||||||
handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut), std::move(cgiStdErr));
|
handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut), std::move(cgiStdErr));
|
||||||
|
|
||||||
handler_.setPid(_pid);
|
handler_.setPid(pid_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CgiProcess::kill() const noexcept
|
void CgiProcess::kill() const noexcept
|
||||||
{
|
{
|
||||||
if (_pid > 0)
|
if (pid_ > 0)
|
||||||
{
|
{
|
||||||
::kill(_pid, SIGKILL);
|
::kill(pid_, SIGKILL);
|
||||||
Log::debug("Killed CGI process with PID: " + std::to_string(_pid));
|
Log::debug("Killed CGI process with PID: " + std::to_string(pid_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CgiProcess::wait() noexcept
|
void CgiProcess::wait() noexcept
|
||||||
{
|
{
|
||||||
if (_pid > 0)
|
if (pid_ > 0)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
int waitResult = ::waitpid(_pid, &status, WNOHANG);
|
int waitResult = ::waitpid(pid_, &status, WNOHANG);
|
||||||
if (waitResult == -1)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (waitResult == 0)
|
if (waitResult == 0)
|
||||||
@ -134,8 +133,13 @@ void CgiProcess::wait() noexcept
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug("CGI process with PID " + std::to_string(_pid) + " has terminated");
|
Log::debug("CGI process with PID " + std::to_string(pid_) + " has terminated with status " + std::to_string(status));
|
||||||
;
|
status_ = status;
|
||||||
_pid = -1;
|
pid_ = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CgiProcess::getExitCode() const noexcept
|
||||||
|
{
|
||||||
|
return status_;
|
||||||
|
}
|
||||||
@ -20,11 +20,14 @@ class CgiProcess
|
|||||||
void kill() const noexcept;
|
void kill() const noexcept;
|
||||||
void wait() noexcept;
|
void wait() noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] int getExitCode() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const HttpRequest &request_;
|
const HttpRequest &request_;
|
||||||
CgiHandler &handler_;
|
CgiHandler &handler_;
|
||||||
|
|
||||||
int _pid;
|
int pid_;
|
||||||
|
int status_;
|
||||||
// int _cgiFd;
|
// int _cgiFd;
|
||||||
|
|
||||||
void spawn();
|
void spawn();
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
|
||||||
|
|
||||||
#include <webserv/http/HttpConstants.hpp> // for CRLF
|
#include <webserv/http/HttpConstants.hpp> // for CRLF
|
||||||
|
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
||||||
#include <webserv/log/Log.hpp>
|
#include <webserv/log/Log.hpp>
|
||||||
#include <webserv/utils/utils.hpp> // for trim
|
#include <webserv/utils/utils.hpp> // for trim
|
||||||
|
|
||||||
#include <algorithm> // for __transform_fn, transform
|
#include <algorithm> // for __transform_fn, transform
|
||||||
#include <cctype> // for tolower
|
#include <cctype> // for tolower
|
||||||
#include <utility> // for pair
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility> // for pair
|
||||||
|
|
||||||
std::optional<size_t> HttpHeaders::getContentLength() const
|
std::optional<size_t> HttpHeaders::getContentLength() const
|
||||||
{
|
{
|
||||||
@ -94,6 +95,11 @@ void HttpHeaders::parse(const std::string &rawHeaders) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, std::string> &HttpHeaders::getAll() const noexcept
|
||||||
|
{
|
||||||
|
return headers_;
|
||||||
|
}
|
||||||
|
|
||||||
std::string HttpHeaders::toString() const noexcept
|
std::string HttpHeaders::toString() const noexcept
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|||||||
@ -29,6 +29,7 @@ class HttpHeaders
|
|||||||
[[nodiscard]] std::optional<size_t> getContentLength() const;
|
[[nodiscard]] std::optional<size_t> getContentLength() const;
|
||||||
[[nodiscard]] std::optional<std::string> getContentType() const noexcept;
|
[[nodiscard]] std::optional<std::string> getContentType() const noexcept;
|
||||||
[[nodiscard]] std::optional<std::string> getHost() const noexcept;
|
[[nodiscard]] std::optional<std::string> getHost() const noexcept;
|
||||||
|
[[nodiscard]] const std::unordered_map<std::string, std::string> &getAll() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::string> headers_;
|
std::unordered_map<std::string, std::string> headers_;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user