feat(Cgi Environment) fix(No function used in process can log or print is will print to the std o that is captured)
This commit is contained in:
parent
0d57ce4f27
commit
ed04838f0d
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
// CGI Capabilities Demonstration Script
|
||||
header("Content-Type: text/html; charset=UTF-8");
|
||||
header("Cache-Control: no-cache, no-store, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
|
||||
54
webserv/handler/CgiEnvironment.cpp
Normal file
54
webserv/handler/CgiEnvironment.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "webserv/handler/CgiEnvironment.hpp"
|
||||
|
||||
#include "webserv/log/Log.hpp"
|
||||
|
||||
#include <cstring> // for strcpy
|
||||
|
||||
CgiEnvironment::CgiEnvironment(const URI &uri, const HttpRequest &request)
|
||||
{
|
||||
env_["GATEWAY_INTERFACE"] = "CGI/1.1";
|
||||
env_["SERVER_PROTOCOL"] = "HTTP/1.1";
|
||||
env_["REQUEST_METHOD"] = request.getMethod();
|
||||
env_["SCRIPT_NAME"] = uri.getBaseName();
|
||||
env_["SCRIPT_FILENAME"] = uri.getFullPath(); // Full filesystem path to the script (required by PHP)
|
||||
env_["QUERY_STRING"] = uri.getQuery();
|
||||
env_["REQUEST_URI"] = request.getTarget();
|
||||
env_["PATH_INFO"] = uri.getPathInfo();
|
||||
|
||||
// Only set CONTENT_TYPE and CONTENT_LENGTH if they have values
|
||||
auto contentType = request.getHeaders().getContentType();
|
||||
if (contentType.has_value())
|
||||
{
|
||||
env_["CONTENT_TYPE"] = contentType.value();
|
||||
}
|
||||
auto contentLength = request.getHeaders().getContentLength();
|
||||
if (contentLength.has_value())
|
||||
{
|
||||
env_["CONTENT_LENGTH"] = std::to_string(contentLength.value());
|
||||
}
|
||||
|
||||
std::string host_port = request.getHeaders().getHost().value_or("");
|
||||
size_t colonPos = host_port.find(':');
|
||||
std::string host = (colonPos != std::string::npos) ? host_port.substr(0, colonPos) : host_port;
|
||||
int port = (colonPos != std::string::npos) ? std::stoi(host_port.substr(colonPos + 1)) : 80;
|
||||
|
||||
env_["SERVER_NAME"] = host;
|
||||
env_["SERVER_PORT"] = std::to_string(port);
|
||||
env_["REMOTE_ADDR"] = "<REMOTE_ADDR>"; // Placeholder, should be set to actual remote address
|
||||
env_["REDIRECT_STATUS"] = "200"; // Required by PHP with force-cgi-redirect enabled
|
||||
|
||||
}
|
||||
|
||||
char **CgiEnvironment::toEnvp() const
|
||||
{
|
||||
char **envp = new char *[env_.size() + 1];
|
||||
size_t index = 0;
|
||||
for (std::map<std::string, std::string>::const_iterator it = env_.begin(); it != env_.end(); ++it, ++index)
|
||||
{
|
||||
std::string entry = it->first + "=" + it->second;
|
||||
envp[index] = new char[entry.size() + 1];
|
||||
std::strcpy(envp[index], entry.c_str());
|
||||
}
|
||||
envp[index] = nullptr; // Null-terminate the array
|
||||
return envp;
|
||||
}
|
||||
21
webserv/handler/CgiEnvironment.hpp
Normal file
21
webserv/handler/CgiEnvironment.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "webserv/handler/URI.hpp"
|
||||
#include "webserv/http/HttpRequest.hpp"
|
||||
#include "webserv/utils/FileUtils.hpp"
|
||||
#include "webserv/log/Log.hpp"
|
||||
|
||||
class CgiEnvironment
|
||||
{
|
||||
public:
|
||||
CgiEnvironment(const URI &uri, const HttpRequest &request);
|
||||
|
||||
[[nodiscard]] char **toEnvp() const;
|
||||
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> env_;
|
||||
|
||||
};
|
||||
@ -121,6 +121,7 @@ void CgiHandler::parseCgiOutput()
|
||||
Log::debug("CGI output headers not complete yet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the headers
|
||||
std::string headers(buffer_.begin(), buffer_.begin() + static_cast<long>(headerEnd));
|
||||
Log::debug("CGI output headers: " + headers);
|
||||
@ -133,24 +134,51 @@ void CgiHandler::parseCgiOutput()
|
||||
void CgiHandler::parseCgiHeaders(std::string &headers)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
|
||||
// Debug: log the raw headers to see what we're getting
|
||||
Log::debug("Raw CGI headers (length=" + std::to_string(headers.length()) + "): [" + headers + "]");
|
||||
|
||||
size_t start = 0;
|
||||
size_t end = headers.find("\r\n");
|
||||
while (end != std::string::npos)
|
||||
{
|
||||
std::string header = headers.substr(start, end - start);
|
||||
Log::debug("CGI header: " + header);
|
||||
size_t colonPos = header.find(':');
|
||||
if (colonPos != std::string::npos)
|
||||
if (!header.empty())
|
||||
{
|
||||
std::string name = header.substr(0, colonPos);
|
||||
std::string value = header.substr(colonPos + 1);
|
||||
name = utils::trim(name);
|
||||
value = utils::trim(value);
|
||||
response_.addHeader(name, value);
|
||||
Log::debug("CGI header: [" + header + "]");
|
||||
size_t colonPos = header.find(':');
|
||||
if (colonPos != std::string::npos)
|
||||
{
|
||||
std::string name = header.substr(0, colonPos);
|
||||
std::string value = header.substr(colonPos + 1);
|
||||
name = utils::trim(name);
|
||||
value = utils::trim(value);
|
||||
response_.addHeader(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warning("CGI header has no colon: [" + header + "]");
|
||||
}
|
||||
}
|
||||
start = end + 2;
|
||||
end = headers.find("\r\n", start);
|
||||
}
|
||||
|
||||
// // Handle the last header (might not have trailing \r\n)
|
||||
// std::string lastHeader = headers.substr(start);
|
||||
// if (!lastHeader.empty())
|
||||
// {
|
||||
// Log::debug("Last CGI header: [" + lastHeader + "]");
|
||||
// size_t colonPos = lastHeader.find(':');
|
||||
// if (colonPos != std::string::npos)
|
||||
// {
|
||||
// std::string name = lastHeader.substr(0, colonPos);
|
||||
// std::string value = lastHeader.substr(colonPos + 1);
|
||||
// name = utils::trim(name);
|
||||
// value = utils::trim(value);
|
||||
// response_.addHeader(name, value);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void CgiHandler::parseCgiBody()
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "webserv/handler/CgiProcess.hpp"
|
||||
|
||||
#include "webserv/handler/CgiEnvironment.hpp"
|
||||
#include "webserv/http/HttpRequest.hpp"
|
||||
#include "webserv/socket/CgiSocket.hpp"
|
||||
|
||||
@ -28,7 +29,6 @@ void CgiProcess::spawn()
|
||||
{
|
||||
const URI &uri = request_.getUri();
|
||||
auto cgiPath = uri.getCgiPath();
|
||||
auto environment = uri.getCGIEnvironment();
|
||||
|
||||
// pipes
|
||||
|
||||
@ -63,11 +63,12 @@ void CgiProcess::spawn()
|
||||
|
||||
// Prepare arguments
|
||||
std::string fullPath = uri.getFullPath();
|
||||
CgiEnvironment cgiEnv(uri, request_);
|
||||
char *args[] = {const_cast<char *>(cgiPath.c_str()), const_cast<char *>(fullPath.c_str()), nullptr};
|
||||
// Log::debug("With args:", {args[0], args[1]});
|
||||
|
||||
// TODO: Close all FDs
|
||||
execve(const_cast<char *>(cgiPath.c_str()), args, nullptr);
|
||||
execve(const_cast<char *>(cgiPath.c_str()), args, cgiEnv.toEnvp());
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
@ -114,6 +115,7 @@ void CgiProcess::wait() noexcept
|
||||
}
|
||||
|
||||
Log::debug("CGI process with PID " + std::to_string(_pid) + " has terminated");
|
||||
;
|
||||
_pid = -1;
|
||||
}
|
||||
}
|
||||
@ -101,7 +101,7 @@ void URI::parseFullpath()
|
||||
}
|
||||
else if (!baseName_.empty()) // not file or dir, but we have a baseName already
|
||||
{
|
||||
pathInfo_ = FileUtils::joinPath(pathInfo_, baseName_);
|
||||
pathInfo_ = FileUtils::joinPath(pathInfo_, segment);
|
||||
}
|
||||
else // not file or dir, and no baseName yet
|
||||
{
|
||||
@ -113,28 +113,28 @@ void URI::parseFullpath()
|
||||
fullPath_ = FileUtils::joinPath(dir_, baseName_);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> URI::getCGIEnvironment() const
|
||||
{
|
||||
std::map<std::string, std::string> env;
|
||||
// std::map<std::string, std::string> URI::getCGIEnvironment() const
|
||||
// {
|
||||
// std::map<std::string, std::string> env;
|
||||
|
||||
// URI components
|
||||
env["REQUEST_URI"] = uriTrimmed_;
|
||||
env["SCRIPT_NAME"] = getFullPath();
|
||||
env["PATH_INFO"] = getPathInfo();
|
||||
env["QUERY_STRING"] = getQuery();
|
||||
// // URI components
|
||||
// env["REQUEST_URI"] = uriTrimmed_;
|
||||
// env["SCRIPT_NAME"] = getFullPath();
|
||||
// env["PATH_INFO"] = getPathInfo();
|
||||
// env["QUERY_STRING"] = getQuery();
|
||||
|
||||
// Authority components
|
||||
env["SERVER_NAME"] = config_->get<std::string>("server_name").value_or("");
|
||||
env["SERVER_PORT"] = std::to_string(config_->get<int>("listen").value_or(-1));
|
||||
env["REQUEST_SCHEME"] = "HTTP";
|
||||
// // Authority components
|
||||
// env["SERVER_NAME"] = config_->get<std::string>("server_name").value_or("");
|
||||
// env["SERVER_PORT"] = std::to_string(config_->get<int>("listen").value_or(-1));
|
||||
// env["REQUEST_SCHEME"] = "HTTP";
|
||||
|
||||
// HTTP context
|
||||
// env["REQUEST_METHOD"] = requestMethod_;
|
||||
// env["CONTENT_TYPE"] = contentType_;
|
||||
// env["CONTENT_LENGTH"] = contentLength_;
|
||||
// // HTTP context
|
||||
// // env["REQUEST_METHOD"] = requestMethod_;
|
||||
// // env["CONTENT_TYPE"] = contentType_;
|
||||
// // env["CONTENT_LENGTH"] = contentLength_;
|
||||
|
||||
return env;
|
||||
}
|
||||
// return env;
|
||||
// }
|
||||
|
||||
const AConfig *URI::getConfig() const noexcept
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
||||
#include <webserv/server/Server.hpp>
|
||||
|
||||
#include <map> // for map
|
||||
|
||||
#include <string> // for string, basic_string
|
||||
|
||||
class LocationConfig;
|
||||
@ -18,8 +18,6 @@ class URI
|
||||
public:
|
||||
URI(const HttpRequest &request, const ServerConfig &serverConfig);
|
||||
|
||||
[[nodiscard]] std::map<std::string, std::string> getCGIEnvironment() const;
|
||||
|
||||
[[nodiscard]] bool isFile() const noexcept;
|
||||
[[nodiscard]] bool isDirectory() const noexcept;
|
||||
[[nodiscard]] bool isValid() const noexcept;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user