feat: cgi headers: enhance CGI handling with output parsing and buffer management
This commit is contained in:
parent
60405f03d5
commit
0c081bbb2c
@ -1,6 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
// CGI Capabilities Demonstration Script
|
// CGI Capabilities Demonstration Script
|
||||||
header("Content-Type: text/html; charset=UTF-8");
|
header("Content-Type: text/html; charset=UTF-8");
|
||||||
|
header("Cache-Control: no-cache, no-store, must-revalidate");
|
||||||
|
header("Pragma: no-cache");
|
||||||
|
header("Expires: 0");
|
||||||
|
header("X-Content-Type-Options: nosniff");
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <webserv/http/HttpResponse.hpp> // for HttpResponse
|
#include <webserv/http/HttpResponse.hpp> // for HttpResponse
|
||||||
#include <webserv/log/Log.hpp> // for Log
|
#include <webserv/log/Log.hpp> // for Log
|
||||||
#include <webserv/socket/CgiSocket.hpp> // for CgiSocket
|
#include <webserv/socket/CgiSocket.hpp> // for CgiSocket
|
||||||
|
#include <webserv/utils/utils.hpp> // for stoul
|
||||||
|
|
||||||
CgiHandler::CgiHandler(const HttpRequest &request, HttpResponse &response)
|
CgiHandler::CgiHandler(const HttpRequest &request, HttpResponse &response)
|
||||||
: AHandler(request, response), cgiProcess_(nullptr), cgiStdIn_(nullptr), cgiStdOut_(nullptr)
|
: AHandler(request, response), cgiProcess_(nullptr), cgiStdIn_(nullptr), cgiStdOut_(nullptr)
|
||||||
@ -19,7 +20,6 @@ void CgiHandler::handle()
|
|||||||
// Initialize CGI process
|
// Initialize CGI process
|
||||||
cgiProcess_ = std::make_unique<CgiProcess>(request_, *this);
|
cgiProcess_ = std::make_unique<CgiProcess>(request_, *this);
|
||||||
|
|
||||||
|
|
||||||
Log::info("CGI process started and sockets registered");
|
Log::info("CGI process started and sockets registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,14 +72,13 @@ void CgiHandler::read()
|
|||||||
Log::info("CGI process closed stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
Log::info("CGI process closed stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
||||||
request_.getClient().removeCgiSocket(cgiStdOut_.get());
|
request_.getClient().removeCgiSocket(cgiStdOut_.get());
|
||||||
cgiStdOut_ = nullptr;
|
cgiStdOut_ = nullptr;
|
||||||
response_.addHeader("Content-Type", "text/html");
|
parseCgiOutput();
|
||||||
response_.setComplete();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||||
response_.appendBody(std::string(buffer, static_cast<size_t>(bytesRead)));
|
appendToBuffer(buffer, static_cast<size_t>(bytesRead));
|
||||||
Log::debug("Read " + std::to_string(bytesRead)
|
Log::debug("Read " + std::to_string(bytesRead)
|
||||||
+ " bytes from CGI stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
+ " bytes from CGI stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
||||||
}
|
}
|
||||||
@ -109,5 +108,63 @@ void CgiHandler::wait() noexcept
|
|||||||
void CgiHandler::setPid(int pid)
|
void CgiHandler::setPid(int pid)
|
||||||
{
|
{
|
||||||
pid_ = pid;
|
pid_ = pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CgiHandler::parseCgiOutput()
|
||||||
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
|
|
||||||
|
// Parse the headers from the buffer
|
||||||
|
size_t headerEnd = std::string(buffer_.begin(), buffer_.end()).find("\r\n\r\n");
|
||||||
|
if (headerEnd == std::string::npos)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
parseCgiHeaders(headers);
|
||||||
|
|
||||||
|
buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast<long>(headerEnd) + 4);
|
||||||
|
parseCgiBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CgiHandler::parseCgiHeaders(std::string &headers)
|
||||||
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
start = end + 2;
|
||||||
|
end = headers.find("\r\n", start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CgiHandler::parseCgiBody()
|
||||||
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
|
|
||||||
|
// Append the body to the response
|
||||||
|
response_.appendBody(buffer_);
|
||||||
|
response_.setComplete();
|
||||||
|
buffer_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CgiHandler::appendToBuffer(const char *data, size_t length)
|
||||||
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
|
buffer_.insert(buffer_.end(), data, data + length);
|
||||||
}
|
}
|
||||||
@ -26,9 +26,16 @@ class CgiHandler : public AHandler
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager
|
constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager
|
||||||
|
std::vector<uint8_t> buffer_;
|
||||||
|
|
||||||
std::unique_ptr<CgiProcess> cgiProcess_;
|
std::unique_ptr<CgiProcess> cgiProcess_;
|
||||||
std::unique_ptr<CgiSocket> cgiStdIn_;
|
std::unique_ptr<CgiSocket> cgiStdIn_;
|
||||||
std::unique_ptr<CgiSocket> cgiStdOut_;
|
std::unique_ptr<CgiSocket> cgiStdOut_;
|
||||||
|
void parseCgiOutput();
|
||||||
|
void parseCgiHeaders(std::string &headers);
|
||||||
|
void parseCgiBody();
|
||||||
|
void appendToBuffer(const char *data, size_t length);
|
||||||
|
|
||||||
int pid_ = -1;
|
int pid_ = -1;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user