From b9a0714925374c2c48e9fd909a50d166b62d8187 Mon Sep 17 00:00:00 2001 From: adjoly Date: Tue, 15 Jul 2025 20:28:48 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=F0=9F=94=80=E3=80=8D=20merge:=20a=20v?= =?UTF-8?q?ery=20cool=20feature=20has=20been=20merged=20!=20:D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exemples/webpage/get_cgi.py | 39 ++++++++----- includes/server/Cgi.hpp | 57 ++++++++++++++++++- lib/tomlpp | 2 +- src/main.cpp | 7 ++- src/requests_handling/Cgi.cpp | 31 ++++++++-- .../requestImplementation/Get.cpp | 4 +- .../requestImplementation/Post.cpp | 4 +- src/server/Client.cpp | 4 +- src/server/ServerHandle.cpp | 4 +- 9 files changed, 120 insertions(+), 32 deletions(-) diff --git a/exemples/webpage/get_cgi.py b/exemples/webpage/get_cgi.py index d754653..18b8b23 100755 --- a/exemples/webpage/get_cgi.py +++ b/exemples/webpage/get_cgi.py @@ -1,7 +1,9 @@ -#!/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/bin/python3 -# Import modules for CGI handling +#!/usr/bin/env python3 import cgi import cgitb +import time +import os +import sys # Needed for sys.exit() # Enable error reporting cgitb.enable() @@ -9,16 +11,25 @@ cgitb.enable() # Create instance of FieldStorage form = cgi.FieldStorage() -# Set the content type to HTML -print("Content-Type: text/html\n") +try: + # Set the content type to HTML + print("Content-Type: text/html\n") -# Output a simple HTML page -print("") -print("") -print("CGI Script Test") -print("") -print("") -print("

CGI Script is Running

") -print("

Your web server is working correctly!

") -print("") -print("") + # Output a simple HTML page + print("") + print("") + print("CGI Script Test") + print("") + print("") + print("

CGI Script is Running

") + print("

Your web server is working correctly!

") + files = os.listdir('.') + for file in files: + print(file) + print("") + print("") + +except Exception: + # Print error page and exit with error code + cgitb.handler() + sys.exit(1) diff --git a/includes/server/Cgi.hpp b/includes/server/Cgi.hpp index e8661b0..eddbb14 100644 --- a/includes/server/Cgi.hpp +++ b/includes/server/Cgi.hpp @@ -6,16 +6,18 @@ /* By: gadelbes +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 13:46:34 by gadelbes #+# #+# */ -/* Updated: 2025/07/11 17:02:37 by adjoly ### ########.fr */ +/* Updated: 2025/07/15 20:27:43 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ #pragma once +#include "log.hpp" #include "server/PfdManager.hpp" #include #include #include +#include #include #include @@ -73,7 +75,7 @@ class Cgi : public server::AClientResource { return false; } - bool isTimedout(void) const { + bool isTimedout(void) { if (!isProcessed() && isReady()) { return false; } @@ -86,6 +88,56 @@ class Cgi : public server::AClientResource { return false; } + bool isErr(void) { + if (_err == true) { + return true; + } + if (_forkPid == -1) { + return false; + } + + int status = 0; + pid_t result = waitpid(_forkPid, &status, WNOHANG); + + if (result == 0 ) { + return false; + } else if (result == -1) { + if (errno == ECHILD) { + _log->warn("CGI child already reaped"); + _err = true; + return true; + } + _log->error("waitpid failed: " + std::string(std::strerror(errno))); + _err = true; + return true; + } + + if (WIFEXITED(status)) { + int code = WEXITSTATUS(status); + if (code != 0) { + std::stringstream str; + str << "CGI exited with status code " << code; + _log->error(str.str()); + _err = true; + return true; + } + return false; + } + + if (WIFSIGNALED(status)) { + std::stringstream str; + str << "CGI terminated by signal: "; + str << WTERMSIG(status); + _log->error(str.str()); + _err = true; + return true; + } + + _log->error("CGI ended abnormally"); + _err = true; + return true; + } + protected: private: bool _is_post; @@ -116,6 +168,7 @@ class Cgi : public server::AClientResource { std::time_t _start_time; // To use for timeout pid_t _forkPid; // Can be used to kill the process + bool _err; }; }; // namespace server diff --git a/lib/tomlpp b/lib/tomlpp index 9930415..a3af54e 160000 --- a/lib/tomlpp +++ b/lib/tomlpp @@ -1 +1 @@ -Subproject commit 9930415a3fdaf5d1b2f8fa84465087703be614ee +Subproject commit a3af54e7919fbeaf2c8b0e78a1ad187884edd752 diff --git a/src/main.cpp b/src/main.cpp index ed534f8..235576c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: mmoussou server::ResourceManager::_res; config::Config * config::_conf = not_nullptr; +server::Server *_server_wtf; } // namespace webserv int _sig = 0; @@ -82,9 +83,9 @@ int main(int ac, char **av) { return EXIT_FAILURE; } - webserv::server::Server *serv = new webserv::server::Server(); + _server_wtf = new webserv::server::Server(); - delete serv; + delete _server_wtf; delete _log; delete config::_conf; } diff --git a/src/requests_handling/Cgi.cpp b/src/requests_handling/Cgi.cpp index b15ebcc..a7c19d2 100644 --- a/src/requests_handling/Cgi.cpp +++ b/src/requests_handling/Cgi.cpp @@ -6,12 +6,13 @@ /* By: gadelbes +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 13:46:34 by gadelbes #+# #+# */ -/* Updated: 2025/07/12 13:22:20 by adjoly ### ########.fr */ +/* Updated: 2025/07/15 20:28:18 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ #include "server/PfdManager.hpp" #include "server/ResourceManager.hpp" +#include #include #include #include @@ -31,10 +32,14 @@ #include #include +webserv::Logger _log; +// webserv::config::Config *config::_conf; +webserv::server::Server *_server_wtf; + using namespace webserv::server; Cgi::Cgi(http::Get *req, config::Route *conf) - : _is_post(false), _conf(conf), _request(req) { + : _is_post(false), _conf(conf), _request(req), _forkPid(-1), _err(false) { _processed = false; log("➕", "Cgi", "GET constructor called"); _initEnvp(); @@ -42,7 +47,7 @@ Cgi::Cgi(http::Get *req, config::Route *conf) } Cgi::Cgi(http::Post *req, config::Route *conf) - : _is_post(true), _conf(conf), _request(req) { + : _is_post(true), _conf(conf), _request(req), _forkPid(-1), _err(false) { _processed = false; log("➕", "Cgi", "POST constructor called"); _initEnvp(); @@ -158,17 +163,35 @@ void Cgi::process(void) { close(_stdout_pipe[PIPE_READ]); close(_stdout_pipe[PIPE_WRITE]); + std::string target = _request->getTarget(); + std::string dir = "/"; + std::size_t pos = target.find_last_of('/'); + if (pos != std::string::npos) + dir = target.substr(0, pos + 1); + chdir((_request->getRoute()->getRootDir() + dir).c_str()); + + std::cerr << _request->getRoute()->getRootDir() + dir << std::endl; + std::cerr << _script_path << std::endl; char * argv[] = {const_cast(_script_path.c_str()), NULL}; char **env = _genEnv(); + _script_path = target.substr(pos + 1); - if (execve(_script_path.c_str(), argv, env) == -1) { + if (execve(_script_path.c_str(), argv, env) == -1) { std::stringstream str; str << "execve failed D:"; str << errno; _log->error(str.str()); + if (_is_post) { + PfdManager::remove(_stdin_pipe[PIPE_WRITE]); + ResourceManager::remove(_stdin_pipe[PIPE_WRITE]); + } for (int i = 0; env[i] != NULL; i++) delete env[i]; delete env; + delete _server_wtf; + delete _log; + delete config::_conf; + exit(EXIT_FAILURE); } } else { diff --git a/src/requests_handling/requestImplementation/Get.cpp b/src/requests_handling/requestImplementation/Get.cpp index 69865f4..a05dada 100644 --- a/src/requests_handling/requestImplementation/Get.cpp +++ b/src/requests_handling/requestImplementation/Get.cpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/30 09:40:16 by adjoly #+# #+# */ -/* Updated: 2025/07/15 19:16:46 by mmoussou ### ########.fr */ +/* Updated: 2025/07/15 20:28:28 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -146,7 +146,7 @@ Response Get::execute(void) { http::Response response; if (_cgi != not_nullptr) { - if (_method == "500" || _cgi->isTimedout()) { + if (_method == "500" || _cgi->isTimedout() || _cgi->isErr()) { response.setStatusCode(500); response.setProtocol(_protocol); response.addHeader("Content-Type", "text/html"); diff --git a/src/requests_handling/requestImplementation/Post.cpp b/src/requests_handling/requestImplementation/Post.cpp index f31032b..c87d77f 100644 --- a/src/requests_handling/requestImplementation/Post.cpp +++ b/src/requests_handling/requestImplementation/Post.cpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/30 09:50:20 by adjoly #+# #+# */ -/* Updated: 2025/07/15 19:17:08 by mmoussou ### ########.fr */ +/* Updated: 2025/07/15 20:28:41 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -166,7 +166,7 @@ Response Post::execute(void) { http::Response response; if (_cgi != not_nullptr) { - if (_method == "500" || _cgi->isTimedout()) { + if (_method == "500" || _cgi->isTimedout() || _cgi->isErr()) { response.setStatusCode(500); response.setProtocol(_protocol); response.addHeader("Content-Type", "text/html"); diff --git a/src/server/Client.cpp b/src/server/Client.cpp index 89e5cec..298f8da 100644 --- a/src/server/Client.cpp +++ b/src/server/Client.cpp @@ -6,7 +6,7 @@ /* By: mmoussou getCgi() != not_nullptr) { if (!_request->getCgi()->isProcessed()) return false; - else if (_request->getCgi()->isTimedout()) + else if (_request->getCgi()->isTimedout() || _request->getCgi()->isErr()) return true; else if (!(PfdManager::get(_request->getCgi()->getId())->revents & _request->getCgi()->event())) diff --git a/src/server/ServerHandle.cpp b/src/server/ServerHandle.cpp index 110cd3c..c482591 100644 --- a/src/server/ServerHandle.cpp +++ b/src/server/ServerHandle.cpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/27 18:22:48 by adjoly #+# #+# */ -/* Updated: 2025/07/02 12:45:52 by adjoly ### ########.fr */ +/* Updated: 2025/07/15 19:17:25 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -130,7 +130,7 @@ void Server::_handle_resource(size_t i) { if (res == not_nullptr) return; - if (res->type() == CGI && static_cast(res)->isTimedout()) { + if (res->type() == CGI && (static_cast(res)->isTimedout() || static_cast(res)->isErr())) { return; } if (!res->isProcessed() && res->isReady()) {