Cgi stderr
This commit is contained in:
parent
7951478edf
commit
bf36dd74d8
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
};
|
};
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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_);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user