Cgi stderr

This commit is contained in:
whaffman 2025-10-21 15:37:45 +02:00
parent 7951478edf
commit bf36dd74d8
7 changed files with 62 additions and 10 deletions

View File

@ -107,13 +107,16 @@ void Client::request()
} }
// //
void Client::setCgiSockets(CgiSocket *cgiStdIn, CgiSocket *cgiStdOut) void Client::setCgiSockets(CgiSocket *cgiStdIn, CgiSocket *cgiStdOut, CgiSocket *cgiStdErr)
{ {
server_.add(*cgiStdIn, EPOLLOUT, this); // write server_.add(*cgiStdIn, EPOLLOUT, this); // write
server_.add(*cgiStdOut, EPOLLIN, this); // read server_.add(*cgiStdOut, EPOLLIN, this); // read
server_.add(*cgiStdErr, EPOLLIN, this); // error
sockets_[cgiStdIn->getFd()] = cgiStdIn; sockets_[cgiStdIn->getFd()] = cgiStdIn;
sockets_[cgiStdOut->getFd()] = cgiStdOut; sockets_[cgiStdOut->getFd()] = cgiStdOut;
sockets_[cgiStdErr->getFd()] = cgiStdErr;
} }
void Client::removeCgiSocket(CgiSocket *cgiSocket) void Client::removeCgiSocket(CgiSocket *cgiSocket)

View File

@ -43,7 +43,7 @@ class Client
[[nodiscard]] ASocket &getSocket(int fd = -1) const; [[nodiscard]] ASocket &getSocket(int fd = -1) const;
// void setStatusCode(int code); // void setStatusCode(int code);
void setCgiSockets(CgiSocket *cgiStdIn, CgiSocket *cgiStdOut); void setCgiSockets(CgiSocket *cgiStdIn, CgiSocket *cgiStdOut, CgiSocket *cgiStdErr);
void removeCgiSocket(CgiSocket *cgiSocket); void removeCgiSocket(CgiSocket *cgiSocket);
[[nodiscard]] HttpRequest &getHttpRequest() const noexcept; [[nodiscard]] HttpRequest &getHttpRequest() const noexcept;

View File

@ -84,15 +84,47 @@ void CgiHandler::read()
} }
} }
void CgiHandler::setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut) void CgiHandler::error()
{
Log::trace(LOCATION);
if (cgiStdErr_ == nullptr)
{
Log::error("CGI stderr socket is null");
return;
}
char buffer[bufferSize_] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays)
ssize_t bytesRead
= cgiStdErr_->read(buffer, sizeof(buffer) - 1); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
if (bytesRead < 0)
{
Log::error("Failed to read from CGI stderr, fd: " + std::to_string(cgiStdErr_->getFd()));
}
else if (bytesRead == 0)
{
Log::info("CGI process closed stderr, fd: " + std::to_string(cgiStdErr_->getFd()));
request_.getClient().removeCgiSocket(cgiStdErr_.get());
cgiStdErr_ = nullptr;
return;
}
else
{
buffer[bytesRead] = '\0'; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
Log::error("CGI stderr output (fd: " + std::to_string(cgiStdErr_->getFd()) + "): "
+ std::string(buffer, static_cast<size_t>(bytesRead)));
}
}
void CgiHandler::setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut, std::unique_ptr<CgiSocket> cgiStdErr)
{ {
cgiStdIn->setCallback([this]() { write(); }); cgiStdIn->setCallback([this]() { write(); });
cgiStdOut->setCallback([this]() { read(); }); cgiStdOut->setCallback([this]() { read(); });
cgiStdErr->setCallback([this]() { error(); });
cgiStdOut_ = std::move(cgiStdOut); cgiStdOut_ = std::move(cgiStdOut);
cgiStdIn_ = std::move(cgiStdIn); cgiStdIn_ = std::move(cgiStdIn);
cgiStdErr_ = std::move(cgiStdErr);
request_.getClient().setCgiSockets(cgiStdIn_.get(), cgiStdOut_.get()); // write request_.getClient().setCgiSockets(cgiStdIn_.get(), cgiStdOut_.get(), cgiStdErr_.get()); // write
// TODO add to handler // TODO add to handler
} }

View File

@ -21,7 +21,7 @@ class CgiHandler : public AHandler
void handle() override; void handle() override;
void wait() noexcept; void wait() noexcept;
void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut); void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut, std::unique_ptr<CgiSocket> cgiStdErr);
void setPid(int pid); void setPid(int pid);
private: private:
@ -31,6 +31,7 @@ class CgiHandler : public AHandler
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_;
std::unique_ptr<CgiSocket> cgiStdErr_;
void parseCgiOutput(); void parseCgiOutput();
void parseCgiHeaders(std::string &headers); void parseCgiHeaders(std::string &headers);
void parseCgiBody(); void parseCgiBody();
@ -41,4 +42,5 @@ class CgiHandler : public AHandler
void write(); void write();
void read(); void read();
void error();
}; };

View File

@ -8,6 +8,7 @@
#include <csignal> #include <csignal>
#include <cstdlib> #include <cstdlib>
#include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
@ -34,8 +35,9 @@ void CgiProcess::spawn()
int pipeStdin[2]; int pipeStdin[2];
int pipeStdout[2]; int pipeStdout[2];
int pipeStderr[2];
if (pipe(pipeStdin) == -1 || pipe(pipeStdout) == -1) if (pipe(pipeStdin) == -1 || pipe(pipeStdout) == -1 || pipe(pipeStderr) == -1)
{ {
throw std::runtime_error("Failed to create pipes"); throw std::runtime_error("Failed to create pipes");
} }
@ -47,19 +49,25 @@ void CgiProcess::spawn()
close(pipeStdin[1]); close(pipeStdin[1]);
close(pipeStdout[0]); close(pipeStdout[0]);
close(pipeStdout[1]); close(pipeStdout[1]);
close(pipeStderr[0]);
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);
dup2(pipeStderr[1], STDERR_FILENO);
close(pipeStdin[0]); close(pipeStdin[0]);
close(pipeStdin[1]); close(pipeStdin[1]);
close(pipeStdout[0]); close(pipeStdout[0]);
close(pipeStdout[1]); close(pipeStdout[1]);
close(pipeStderr[0]);
close(pipeStderr[1]);
// Log::debug("Executing CGI: " + cgiPath); // Log::debug("Executing CGI: " + cgiPath);
std::cerr << "Executing CGI: " << cgiPath << std::endl;
// Prepare arguments // Prepare arguments
std::string fullPath = uri.getFullPath(); std::string fullPath = uri.getFullPath();
@ -76,14 +84,17 @@ void CgiProcess::spawn()
// Parent process // Parent process
auto cgiStdIn = std::make_unique<CgiSocket>(pipeStdin[1]); auto cgiStdIn = std::make_unique<CgiSocket>(pipeStdin[1]);
auto cgiStdOut = std::make_unique<CgiSocket>(pipeStdout[0]); auto cgiStdOut = std::make_unique<CgiSocket>(pipeStdout[0]);
auto cgiStdErr = std::make_unique<CgiSocket>(pipeStderr[0]);
close(pipeStdin[0]); close(pipeStdin[0]);
close(pipeStdout[1]); 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 // request_.getClient().setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); // move the sockets to the
// client // client
handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut)); handler_.setCgiSockets(std::move(cgiStdIn), std::move(cgiStdOut), std::move(cgiStdErr));
handler_.setPid(_pid); handler_.setPid(_pid);
} }
} }

View File

@ -103,6 +103,11 @@ void URI::parseFullpath()
} }
else if (!baseName_.empty()) // not file or dir, but we have a baseName already else if (!baseName_.empty()) // not file or dir, but we have a baseName already
{ {
if (pathInfo_.empty())
{
pathInfo_ = "/";
}
pathInfo_ = FileUtils::joinPath(pathInfo_, segment); pathInfo_ = FileUtils::joinPath(pathInfo_, segment);
} }
else // not file or dir, and no baseName yet else // not file or dir, and no baseName yet
@ -124,8 +129,7 @@ void URI::parseFullpath()
} }
} }
} }
Log::debug("URI parseFullpath results", Log::debug("URI parseFullpath results", {{"dir", dir_}, {"baseName", baseName_}, {"pathInfo", pathInfo_}});
{{"dir", dir_}, {"baseName", baseName_}, {"pathInfo", pathInfo_}});
fullPath_ = FileUtils::joinPath(dir_, baseName_); fullPath_ = FileUtils::joinPath(dir_, baseName_);
} }

View File

@ -23,7 +23,7 @@ ASocket::ASocket(int fd) : fd_(fd)
ASocket::~ASocket() ASocket::~ASocket()
{ {
Log::trace(LOCATION); Log::trace(LOCATION + "Closing socket fd: " + std::to_string(fd_));
if (fd_ != -1) if (fd_ != -1)
{ {
close(fd_); close(fd_);