From 0887acd81a59919381567156010bb35aaa159b50 Mon Sep 17 00:00:00 2001 From: Quinten Date: Wed, 15 Oct 2025 17:03:49 +0200 Subject: [PATCH] feat(config): add new server configuration for site-3 and implement CGI support feat(site-3): create index.php for site-3 with a greeting message refactor(client): change setCgiSocket to accept unique_ptr for better memory management fix(AConfig): adjust getCGIPath to correctly prepend dot to extension refactor(CgiProcess): update CGI process handling to use unique_ptr for CgiSocket refactor(URI): enhance logging for CGI checks and improve condition checks refactor(Router): clean up commented code and add debug logging for CGI process fix(Server): improve error logging for epoll_ctl failures --- config/default.conf | 29 +++++++++++++++++++++++++++++ htdocs/site-3/index.php | 3 +++ webserv/client/Client.cpp | 12 ++++++++---- webserv/client/Client.hpp | 3 ++- webserv/config/AConfig.cpp | 2 +- webserv/handler/CgiProcess.cpp | 14 +++++++++----- webserv/handler/URI.cpp | 12 ++++++++++-- webserv/router/Router.cpp | 19 +++++++------------ webserv/server/Server.cpp | 6 +++--- 9 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 htdocs/site-3/index.php diff --git a/config/default.conf b/config/default.conf index 70c69d4..1b247f3 100644 --- a/config/default.conf +++ b/config/default.conf @@ -87,4 +87,33 @@ server { # cgi_enabled yes; cgi_ext .php /usr/bin/php-cgi; +} + +server { + listen 8082; + host 127.0.0.1; + server_name localhost; + + root ./htdocs/site-3/; + index index.html index2.htm; + + error_page 400; + error_page 403 /403.html; + error_page 404 /404.html; + error_page 405 /405.html; + error_page 413 /413.html; + error_page 500 /500.html; + error_page 502 /502.html; + error_page 504 /504.html; + + client_max_body_size 1M; + + location / { + autoindex off; + index index.php; + allowed_methods GET POST DELETE; + } + + cgi_enabled yes; + cgi_ext .php /usr/bin/php-cgi; } \ No newline at end of file diff --git a/htdocs/site-3/index.php b/htdocs/site-3/index.php new file mode 100644 index 0000000..bb5f6a6 --- /dev/null +++ b/htdocs/site-3/index.php @@ -0,0 +1,3 @@ + #include // for HttpHeaders #include // for Log, LOCATION @@ -9,8 +11,9 @@ #include #include // for ref, reference_wrapper #include // for map -#include // for basic_string, to_string, operator+, operator<=> -#include // for pair, move +#include +#include // for basic_string, to_string, operator+, operator<=> +#include // for pair, move #include #include // for ssize_t @@ -86,9 +89,10 @@ void Client::request() } } -void Client::setCgiSocket(CgiSocket &cgiSocket) +void Client::setCgiSocket(std::unique_ptr cgiSocket) { - server_.add(cgiSocket, EPOLLIN | EPOLLOUT); + server_.add(*cgiSocket, EPOLLIN, this); + cgi_socket_ = std::move(cgiSocket); // TODO add to handler } diff --git a/webserv/client/Client.hpp b/webserv/client/Client.hpp index 2907e07..f68c9ef 100644 --- a/webserv/client/Client.hpp +++ b/webserv/client/Client.hpp @@ -43,7 +43,7 @@ class Client [[nodiscard]] ClientSocket &getSocket() const { return *client_socket_; } void setStatusCode(int code); - void setCgiSocket(CgiSocket &cgiSocket); + void setCgiSocket(std::unique_ptr cgiSocket); [[nodiscard]] HttpRequest &getHttpRequest() const; [[nodiscard]] HttpResponse &getHttpResponse() const; @@ -55,5 +55,6 @@ class Client std::unique_ptr httpResponse_; std::unique_ptr router_; std::unique_ptr client_socket_; + std::unique_ptr cgi_socket_ = nullptr; Server &server_; }; \ No newline at end of file diff --git a/webserv/config/AConfig.cpp b/webserv/config/AConfig.cpp index 1f71dd6..14ead75 100644 --- a/webserv/config/AConfig.cpp +++ b/webserv/config/AConfig.cpp @@ -130,7 +130,7 @@ std::string AConfig::getCGIPath(const std::string &extension) const auto exts = directive->getValue().try_get>().value(); auto cgiPath = exts.back(); exts.pop_back(); // Last element is the CGI path - auto it = std::ranges::find(exts, extension); + auto it = std::ranges::find(exts, "." + extension); if (it != exts.end()) { return cgiPath; diff --git a/webserv/handler/CgiProcess.cpp b/webserv/handler/CgiProcess.cpp index 8c31a13..b8b08f0 100644 --- a/webserv/handler/CgiProcess.cpp +++ b/webserv/handler/CgiProcess.cpp @@ -5,6 +5,9 @@ #include +#include +#include + #include #include @@ -47,17 +50,18 @@ void CgiProcess::spawn() close(sv[1]); // Prepare arguments - char *args[] = {const_cast(cgiPath.c_str()), nullptr}; + std::string fullPath = uri.getFullPath(); + char *args[] = {const_cast(cgiPath.c_str()), const_cast(fullPath.c_str())}; execve(const_cast(cgiPath.c_str()), args, nullptr); } else { // Parent process - CgiSocket cgiSocket(sv[0]); - close(sv[0]); + auto cgiSocket = std::make_unique(sv[0]); // CgiSocket wraps sv[0] + close(sv[1]); - request_.getClient().setCgiSocket(cgiSocket); // move the socket to the client - cgiSocket.write(request_.getBody().data(), request_.getBody().size()); + // cgiSocket->write(request_.getBody().data(), request_.getBody().size()); + request_.getClient().setCgiSocket(std::move(cgiSocket)); // move the socket to the client // _cgiFd can be used to communicate with the CGI process } } \ No newline at end of file diff --git a/webserv/handler/URI.cpp b/webserv/handler/URI.cpp index 38b0f59..9cae07c 100644 --- a/webserv/handler/URI.cpp +++ b/webserv/handler/URI.cpp @@ -1,4 +1,5 @@ #include "webserv/log/Log.hpp" + #include // for AConfig #include // for LocationConfig #include // for ServerConfig @@ -155,9 +156,16 @@ bool URI::isCgi() const std::string URI::getCgiPath() const { - if (isFile() || getExtension().empty() || !config_->get("cgi_enabled").has_value() - || config_->get("cgi_enabled").value() != "on") + Log::debug("BaseName: " + baseName_ + ", FullPath: " + fullPath_ + ", Dir: " + dir_ + ", PathInfo: " + pathInfo_ + + ", Extension: " + getExtension()); + if (!isFile() || getExtension().empty() || !config_->get("cgi_enabled").has_value() + || !config_->get("cgi_enabled").value()) { + Log::debug("CGI not enabled or not a file or no extension", + {{"isFile", isFile() ? "true" : "false"}, + {"extension", getExtension()}, + {"cgi_enabled", config_->get("cgi_enabled").has_value() ? "true" : "false"}, + {"cgi_enabled_value", config_->get("cgi_enabled").value() ? "true" : "false"}}); return ""; } auto cgiPath = config_->getCGIPath(getExtension()); diff --git a/webserv/router/Router.cpp b/webserv/router/Router.cpp index dd2733f..4a21aa5 100644 --- a/webserv/router/Router.cpp +++ b/webserv/router/Router.cpp @@ -40,21 +40,12 @@ void Router::handleRequest() HttpRequest &request = client_->getHttpRequest(); HttpResponse &response = client_->getHttpResponse(); - // ServerConfig *serverConfig - // = ConfigManager::getInstance().getMatchingServerConfig(request.getHeaders().getHost().value_or("")); - - // if (serverConfig == nullptr) - // { - // response = ErrorHandler::getErrorResponse(400); - // } - // URI uri{request, *serverConfig}; - const std::string &target = request.getTarget(); static_cast(target); // Suppress unused variable warning const std::string &method = request.getMethod(); const AConfig *config = request.getUri().getConfig(); - + if (!isMethodSupported(method, *config)) { // return ErrorHandler::getErrorResponse(405, config); @@ -63,6 +54,7 @@ void Router::handleRequest() { try { + Log::debug("Starting CGI process"); CgiProcess cgiProcess(request); // return nullptr; // Response will be handled asynchronously } @@ -72,6 +64,9 @@ void Router::handleRequest() // return ErrorHandler::getErrorResponse(500, config); } } - FileHandler fileHandler(request, response); - fileHandler.handle(); + else + { + FileHandler fileHandler(request, response); + fileHandler.handle(); + } } \ No newline at end of file diff --git a/webserv/server/Server.cpp b/webserv/server/Server.cpp index 4cb177b..d610c06 100644 --- a/webserv/server/Server.cpp +++ b/webserv/server/Server.cpp @@ -73,7 +73,7 @@ void Server::add(const ASocket &socket, uint32_t events, Client *client) event.data.fd = fd; if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event) == -1) { - Log::error("epoll_ctl ADD failed for fd: " + std::to_string(fd)); + Log::error("epoll_ctl ADD failed for fd: " + std::to_string(fd) + " with error: " + std::strerror(errno)); throw std::runtime_error("epoll_ctl ADD failed"); } socketToClient_[fd] = client; @@ -185,8 +185,8 @@ void Server::handleResponse(struct epoll_event *event) { Log::debug("Attempting to send data to fd: " + std::to_string(event->data.fd)); Client &client = getClient(event->data.fd); - auto httpResponse = client.getResponse(); - ssize_t bytesSent = send(event->data.fd, httpResponse.data(), httpResponse.size(), 0); + auto payload = client.getResponse(); + ssize_t bytesSent = send(event->data.fd, payload.data(), payload.size(), 0); if (bytesSent < 0) { Log::error("Send failed for fd: " + std::to_string(event->data.fd) + " with error: " + std::strerror(errno));