diff --git a/Makefile b/Makefile index 626bcaf..3e910ee 100644 --- a/Makefile +++ b/Makefile @@ -65,11 +65,11 @@ cgire: clean: rm -rf $(OBJS_D) - echo "$(_RED).o Files Deleted 😱$(_END)" + echo "$(_CYAN).o Files Deleted 🤫$(_END)" fclean: clean rm -f $(NAME) - echo "$(_RED)$(NAME) Deleted 😱$(_END)" + echo "$(_CYAN)$(NAME) Deleted 🤫$(_END)" re: fclean all diff --git a/memo.txt b/memo.txt index 1604417..a0b9fd1 100644 --- a/memo.txt +++ b/memo.txt @@ -7,21 +7,12 @@ - handle redirection (Work, but weird behavior need deeper test) - Ecrire des tests ! -- cgi_cpp_status.cpp with POST dont show error page. Normal or not ? - -- check status in autoindex - -- merge changes from hugo5 to master (attention a pas casse svp :clown:) - --- changer le 4040 port par default cgi - ----Priorité modérée------------------------ - namespace utils ? - change "std::string" to reference "std::string &" in most functions and add "const" if apropriate. - peut-être check si ip > 32bits - ----Priorité faible------------------------ - idealy, we should not clear() raw_request after a response, but just the part we actually parsed for this response. diff --git a/srcs/Client.cpp b/srcs/Client.cpp index e34e5fc..972bbb6 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -112,7 +112,6 @@ void Client::parse_request_headers(std::vector &servers) _check_request_errors(); if (status) return; - _parse_port_hostname(get_rq_headers("Host")); // use getter for headers because it works case insensitive // DEBUG // std::cerr << get_rq_method_str() << " " << get_rq_target() << " " << get_rq_version() << "\n"; @@ -260,8 +259,6 @@ void Client::clear_request_vars() _request.multi_bodys.clear(); _request.abs_path.clear(); _request.query.clear(); - _request.port.clear(); - _request.hostname.clear(); } void Client::clear_script() @@ -298,8 +295,6 @@ std::cout << "\n=== DEBUG PRINT CLIENT ===\n"; << "get_rq_query() : [" << get_rq_query() << "]\n" << "get_rq_version() : [" << get_rq_version() << "]\n" << "get_rq_body() : [" << get_rq_body() << "]\n" - << "get_rq_port() : [" << get_rq_port() << "]\n" - << "get_rq_hostname() : [" << get_rq_hostname() << "]\n" << "get_rq_script_path() : [" << get_rq_script_path() << "]\n" << "get_rq_script_info() : [" << get_rq_script_info() << "]\n" << "headers :\n"; @@ -327,8 +322,6 @@ std::string Client::get_rq_abs_path() const { return _request.abs_path; } std::string Client::get_rq_query() const { return _request.query; } std::string Client::get_rq_version() const { return _request.version; } std::string Client::get_rq_body() const { return _request.body; } -std::string Client::get_rq_port() const { return _request.port; } -std::string Client::get_rq_hostname() const { return _request.hostname; } std::string Client::get_rq_script_path()const { return _request.script.path; } std::string Client::get_rq_script_info()const { return _request.script.info; } @@ -411,26 +404,6 @@ void Client::_parse_request_fields() ::str_map_key_tolower(_request.headers); } -// TODO : I think its now useless. Probably to delete. -void Client::_parse_port_hostname(std::string host) -{ - size_t pos; - - if (host == "") - std::cerr << "no host\n"; - - pos = host.find(':'); - // port : - if (pos == NPOS) - _request.port = "4040"; // TODO: make equal to default port in config - else - _request.port = host.substr(pos); - if (_request.port == ":") - _request.port = ""; - // hostname : - _request.hostname = host.substr(0, pos); -} - void Client::_check_request_errors() { // /* Debug */ std::cerr << "Content-Length=" << get_rq_headers("Content-Length") << "\n"; diff --git a/srcs/Client.hpp b/srcs/Client.hpp index 56536d7..ef1a011 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -35,8 +35,6 @@ struct Request std::map headers; std::string body; std::vector multi_bodys; - std::string port; - std::string hostname; struct Script script; }; @@ -64,7 +62,6 @@ class Client bool header_complete; bool body_complete; bool request_complete; - // size_t read_body_size; // unused for now ServerConfig *assigned_server; // cant be const cause of error_pages.operator[] const LocationConfig *assigned_location; @@ -91,8 +88,6 @@ class Client std::string get_rq_query() const; std::string get_rq_version() const; std::string get_rq_body() const; - std::string get_rq_port() const; - std::string get_rq_hostname() const; std::string get_rq_script_path() const; std::string get_rq_script_info() const; std::string get_rq_headers(const std::string & key) const; @@ -120,7 +115,6 @@ class Client void _parse_request_line(); void _parse_request_fields(); void _parse_request_target( std::string target ); - void _parse_port_hostname(std::string host); void _parse_chunked_body(size_t pos); void _parse_multipart_body(size_t pos); void _check_request_errors(); diff --git a/srcs/Client_multipart_body.cpp b/srcs/Client_multipart_body.cpp index 89cf083..144fc79 100644 --- a/srcs/Client_multipart_body.cpp +++ b/srcs/Client_multipart_body.cpp @@ -36,8 +36,6 @@ void Client::_parse_multipart_body(size_t pos) } start_pos += sizeof("boundary=")-1; boundary = boundary.substr(start_pos); - std::cerr << "boundary =|" << boundary << "|\n"; - // Search boundary start_pos = raw_request.find("--" + boundary, pos); @@ -48,7 +46,7 @@ void Client::_parse_multipart_body(size_t pos) } start_pos += sizeof("--")-1 + boundary.size() + CRLF_SIZE; - while (1) // TODO : test loop for multi body + while (1) { end_pos = raw_request.find("--" + boundary, start_pos); if (end_pos == NPOS) @@ -56,9 +54,6 @@ void Client::_parse_multipart_body(size_t pos) status = 400; std::cerr << "_parse_multipart_body() error 3\n"; return; } - /* // Maye useful for multi body (remove "start_pos - CRLF_SIZE" if used) - end_pos = raw_request.rfind(CRLF, end_pos); if (end_pos == NPOS) {status = 400; return; } */ - new_body.body = raw_request.substr(start_pos, end_pos - start_pos - CRLF_SIZE); // Split headers from body @@ -74,7 +69,6 @@ void Client::_parse_multipart_body(size_t pos) } tmp_pos += CRLF_SIZE*2; new_body.body.erase(0, tmp_pos); - // ::print_map(new_body.headers); } else { // No headers case @@ -94,10 +88,5 @@ void Client::_parse_multipart_body(size_t pos) && raw_request[start_pos] == '-' && raw_request[start_pos+1] == '-') break; - -/* ::print_special(raw_request); - std::cerr << "start_pos = " << start_pos << "\n"; - std::cerr << "raw_request.size() = " << raw_request.size() << "\n"; - std::cerr << raw_request.substr(start_pos); */ } } diff --git a/srcs/cgi-bin/Makefile b/srcs/cgi-bin/Makefile index a32e969..8eda238 100644 --- a/srcs/cgi-bin/Makefile +++ b/srcs/cgi-bin/Makefile @@ -92,4 +92,3 @@ fclean: clean re: fclean all .PHONY : all clean fclean re - diff --git a/srcs/config/ConfigParser.hpp b/srcs/config/ConfigParser.hpp index 0d5bf91..a11bacd 100644 --- a/srcs/config/ConfigParser.hpp +++ b/srcs/config/ConfigParser.hpp @@ -14,46 +14,41 @@ # include // strtol, stroul # include // cout, cin # include // ifstream -# include // stat(), replaces opendir() don't bother with ERRNO ? # include // sort() in Post class ConfigParser { -public: + public: - ConfigParser(); - ~ConfigParser(); - ConfigParser(const std::string &config_file); + ConfigParser(); + ~ConfigParser(); + ConfigParser(const std::string &config_file); - void read_config(const std::string &config_file); + void read_config(const std::string &config_file); - std::vector * parse(); // const? + std::vector *parse() const; + void print_content() const; -// i thought if it were an instance of this class you could call -// private member functions from anywhere... // QUESTION : Wut ? - void print_content() const; + private: + std::string _content; + ServerConfig _parse_server(size_t *start) const; + LocationConfig _parse_location(size_t *start) const; -private: - std::string _content; + void _set_server_values(ServerConfig *server, const std::string &key, std::string value) const; + void _set_location_values(LocationConfig *location, const std::string &key, std::string value) const; - ServerConfig _parse_server(size_t *start); - LocationConfig _parse_location(size_t *start); + /* Extra */ + std::string _pre_set_val_check(const std::string &key, + const std::string &value) const; - void _set_server_values(ServerConfig *server, const std::string key, std::string value); - void _set_location_values(LocationConfig *location, const std::string key, std::string value); + std::string _get_first_word(size_t *curr) const; + std::string _get_rest_of_line(size_t *curr) const; -/* Extra */ - std::string _pre_set_val_check(const std::string key, - const std::string value); - - std::string _get_first_word(size_t *curr); // const? - std::string _get_rest_of_line(size_t *curr); // const? - -/* Post Processing */ - void _post_processing(std::vector *servers); - bool _find_root_path_location(std::vector locations) const; + /* Post Processing */ + void _post_processing(std::vector *servers) const; + bool _find_root_path_location(std::vector locations) const; }; diff --git a/srcs/config/extraConfig.cpp b/srcs/config/extraConfig.cpp index 1e2278a..9ff861d 100644 --- a/srcs/config/extraConfig.cpp +++ b/srcs/config/extraConfig.cpp @@ -1,16 +1,13 @@ #include "ConfigParser.hpp" -// should i be sending & references? -// const? -std::string ConfigParser::_pre_set_val_check(const std::string key, - const std::string value) +std::string ConfigParser::_pre_set_val_check(const std::string &key, + const std::string &value) const { // check key for ; // check values for ; at end and right number of words depending on key -// std::cout << "pre check\n"; if (key.find_first_of(";") != NPOS) throw std::invalid_argument("bad config file arguments"); @@ -30,9 +27,8 @@ std::string ConfigParser::_pre_set_val_check(const std::string key, return (value.substr(0, i)); } -// const? // assumes curr is on a space or \t or \n -std::string ConfigParser::_get_first_word(size_t *curr) +std::string ConfigParser::_get_first_word(size_t *curr) const { size_t start; @@ -45,9 +41,8 @@ std::string ConfigParser::_get_first_word(size_t *curr) return (key); } -// const? // also assumes curr is on a space \t or \n -std::string ConfigParser::_get_rest_of_line(size_t *curr) +std::string ConfigParser::_get_rest_of_line(size_t *curr) const { size_t start; diff --git a/srcs/config/parser.cpp b/srcs/config/parser.cpp index f9c450a..283e96f 100644 --- a/srcs/config/parser.cpp +++ b/srcs/config/parser.cpp @@ -41,8 +41,7 @@ void ConfigParser::read_config(const std::string &config_file) } } -// const? -std::vector * ConfigParser::parse() +std::vector * ConfigParser::parse() const { std::vector * ret = new std::vector(); @@ -67,7 +66,7 @@ std::vector * ConfigParser::parse() return (ret); } -ServerConfig ConfigParser::_parse_server(size_t *start) +ServerConfig ConfigParser::_parse_server(size_t *start) const { ServerConfig ret; size_t curr = _content.find_first_not_of(" \t\n", *start); @@ -78,7 +77,6 @@ ServerConfig ConfigParser::_parse_server(size_t *start) if ((curr = _content.find_first_of(" \t\n", curr + 1)) == NPOS) throw std::invalid_argument("bad config file syntax"); - // are there other things to check for? while (curr != NPOS) // here curr == { + 1 { // so this moves curr to past the word... @@ -104,7 +102,7 @@ ServerConfig ConfigParser::_parse_server(size_t *start) -LocationConfig ConfigParser::_parse_location(size_t *start) +LocationConfig ConfigParser::_parse_location(size_t *start) const { LocationConfig ret; size_t curr = *start; @@ -148,11 +146,9 @@ LocationConfig ConfigParser::_parse_location(size_t *start) -// should i be sending pointers or references? void ConfigParser::_set_server_values(ServerConfig *server, - const std::string key, std::string value) + const std::string &key, std::string value) const { -// should i be sending pointers or references? value = _pre_set_val_check(key, value); std::vector tmp_val = ::split(value, ' '); @@ -174,11 +170,11 @@ void ConfigParser::_set_server_values(ServerConfig *server, } } else if (key == "listen" && size == 1 && server->host == "" - && server->port == "") // QUESTION LUKE : C'est quoi cette condition ? Si listen est vide ? Je comprends pas trop. + && server->port == "") { if (tmp_val[0].find_first_of(":") == NPOS) { - if (!::isNumeric_btw(0, 65535, tmp_val[0])) + if (!::is_numeric_btw(0, 65535, tmp_val[0])) throw std::invalid_argument("bad port number"); server->host = "0.0.0.0"; server->port = tmp_val[0]; @@ -192,10 +188,10 @@ void ConfigParser::_set_server_values(ServerConfig *server, throw std::invalid_argument("bad host ip"); for (size_t i = 0; i < ip.size(); i++) { - if (!::isNumeric_btw(0, 255, ip[i])) + if (!::is_numeric_btw(0, 255, ip[i])) throw std::invalid_argument("bad host ip"); } - if (!::isNumeric_btw(0, 65535, tmp2[1])) + if (!::is_numeric_btw(0, 65535, tmp2[1])) throw std::invalid_argument("bad port number"); server->host = tmp2[0]; server->port = tmp2[1]; @@ -206,13 +202,12 @@ void ConfigParser::_set_server_values(ServerConfig *server, // remove trailing / if (tmp_val[0][tmp_val[0].size() - 1] == '/') tmp_val[0].erase(tmp_val[0].size() - 1, 1); - // tmp_val[0].push_back('/'); server->root = tmp_val[0]; } else if (key == "client_body_limit" && size == 1 && server->client_body_limit == 0) { - if (!::isNumeric(tmp_val[0])) + if (!::is_numeric(tmp_val[0])) throw std::invalid_argument("client_body_limit not a number"); server->client_body_limit = std::strtoul(tmp_val[0].c_str(), NULL, 10); if (errno == ERANGE || server->client_body_limit > (ULONG_MAX / KB) ) @@ -229,7 +224,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, std::string path = tmp_val[size - 1]; for (size_t i = 0; i < size - 1; i++) { - if (!(isNumeric_btw(400, 599, tmp_val[i]))) + if (!(is_numeric_btw(400, 599, tmp_val[i]))) throw std::invalid_argument("invalid error code"); int status_code = std::strtoul(tmp_val[i].c_str(), NULL, 10); if (server->error_pages.find(status_code) != server->error_pages.end()) @@ -242,11 +237,9 @@ void ConfigParser::_set_server_values(ServerConfig *server, } -// should i be sending pointers or references? void ConfigParser::_set_location_values(LocationConfig *location, - const std::string key, std::string value) + const std::string &key, std::string value) const { -// should i be sending pointers or references? value = _pre_set_val_check(key, value); std::vector tmp_val = ::split(value, ' '); @@ -259,7 +252,6 @@ void ConfigParser::_set_location_values(LocationConfig *location, // remove trailing / if (tmp_val[0][tmp_val[0].size() - 1] == '/') tmp_val[0].erase(tmp_val[0].size() - 1, 1); -// tmp_val[0].push_back('/'); location->root = tmp_val[0]; } else if (key == "autoindex" && size == 1) @@ -306,7 +298,6 @@ void ConfigParser::_set_location_values(LocationConfig *location, } else if (key == "upload_dir" && size == 1 && location->upload_dir == "") { - // what checks to do? // add trailing / if (tmp_val[0][tmp_val[0].size() - 1] != '/') tmp_val[0].push_back('/'); diff --git a/srcs/config/postProcessing.cpp b/srcs/config/postProcessing.cpp index dfe5ab4..3df661c 100644 --- a/srcs/config/postProcessing.cpp +++ b/srcs/config/postProcessing.cpp @@ -3,21 +3,18 @@ #include "ConfigParser.hpp" -void ConfigParser::_post_processing(std::vector *servers) +void ConfigParser::_post_processing(std::vector *servers) const { std::vector::iterator it = servers->begin(); while (it != servers->end()) { - // host and port are Mandatory if (it->host == "") throw std::invalid_argument("Config file needs a host and port"); - // root is mandatory if (it->root == "") throw std::invalid_argument("Config file needs a root"); - // index is mandatory in Server if (it->index.empty()) throw std::invalid_argument("Config file needs an Index"); diff --git a/srcs/main.cpp b/srcs/main.cpp index 6a6eba7..1b40294 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -15,24 +15,9 @@ int main(int ac, char **av) ConfigParser configParser(config); // configParser.print_content(); - // i don't love that servers_config has to be a pointer... servers_config = configParser.parse(); - - // use an iterator you moron - for (std::vector::iterator it = servers_config->begin(); it < servers_config->end(); it++) - { - (void)0; - // std::cout << it->server_name << " "; - // it->print_all(); - } - - -// Webserv serv(configParser.parse()); - // is this better or worse than using Webserv serv; - - // serv.init_virtual_servers(); serv.init_virtual_servers(servers_config); delete servers_config; servers_config = NULL; diff --git a/srcs/utils.cpp b/srcs/utils.cpp index 4c82845..2cb27ab 100644 --- a/srcs/utils.cpp +++ b/srcs/utils.cpp @@ -1,14 +1,6 @@ #include "utils.hpp" -void throw_test() -{ - static int i = 0; - ++i; - if (i % 8 == 0) - throw std::bad_alloc(); -} - // notice : the use of getline make it such as // it doesn't identify multiple delim as one : // " something \n else " -> 1 - something @@ -72,19 +64,6 @@ std::string trim(std::string str, char del) return str; } -//// trim a set of char -//std::string trim(std::string str, std::string del) -//{ -// std::string new_str; -// -// while (new_str.compare(str) != 0) -// { -// for (size_t i = 0; i < del.size(); i++) -// trim(str, del[i]); -// } -// return str; -//} - std::string itos(int n) { std::stringstream strs; @@ -93,7 +72,7 @@ std::string itos(int n) return ( strs.str() ); } -bool isNumeric(std::string str) +bool is_numeric(std::string str) { for (size_t i = 0; i < str.length(); i++) { @@ -103,7 +82,7 @@ bool isNumeric(std::string str) return true; } -bool isNumeric_btw(int low, int high, std::string str) +bool is_numeric_btw(int low, int high, std::string str) { for (size_t i = 0; i < str.length(); i++) { @@ -155,7 +134,7 @@ file_type eval_file_type(const std::string &path) { struct stat s; - if (stat(path.c_str(), &s) != -1) + if (::stat(path.c_str(), &s) != -1) { if (S_ISREG(s.st_mode)) return (IS_FILE); @@ -305,6 +284,15 @@ void str_map_key_tolower(std::map & mp) } // DEBUG + +void throw_test() +{ + static int i = 0; + ++i; + if (i % 8 == 0) + throw std::bad_alloc(); +} + void print_special(std::string str) { char c; @@ -318,10 +306,12 @@ void print_special(std::string str) std::cout << YELLOW << "\\n" << RESET << "\n"; else std::cout << c; - fflush(stdout); + std::fflush(stdout); } } +// OVERLOADS + bool operator==(const listen_socket& lhs, int fd) { return lhs.fd == fd; } diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 7d00e1b..7090c2c 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -45,8 +45,6 @@ enum http_method POST = 1 << 1, DELETE = 1 << 2, ANY_METHODS = 0b11111111, -// ALL_METHODS = 0b11111111, - // i would prefer this... }; struct listen_socket @@ -60,8 +58,8 @@ bool operator==(int fd, const listen_socket& rhs); std::vector split(std::string input, char delimiter); std::vector split_trim(std::string input, std::string delim = "\n", char ctrim = '\0'); -bool isNumeric(std::string str); -bool isNumeric_btw(int low, int high, std::string str); +bool is_numeric(std::string str); +bool is_numeric_btw(int low, int high, std::string str); std::string itos(int n); std::string trim(std::string str, char del); http_method str_to_http_method(std::string &str); @@ -76,7 +74,7 @@ size_t parse_http_headers (std::string headers, std::map & mp); // debug void throw_test(); -void print_special(std::string str); +void print_special(std::string str); /* Template */ diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 2c6ef2e..625a0e1 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -38,10 +38,6 @@ extern bool g_run; extern int g_last_signal; void signal_handler(int signum); -// these might only be TMP -# define FAILURE -1 -# define SUCCESS 1 - # define MIME_TYPE_DEFAULT "application/octet-stream" class Webserv @@ -49,13 +45,7 @@ class Webserv public: // base.cpp Webserv(); - // Webserv(Webserv const &src); - - // what should it take as arg, *, &, ? -// Webserv(std::vector& servers); - ~Webserv(); - // Webserv &operator=(Webserv const &rhs); // init.cpp void init_virtual_servers(std::vector* servers); diff --git a/srcs/webserv/accept.cpp b/srcs/webserv/accept.cpp index fbadcb4..9fb5e4e 100644 --- a/srcs/webserv/accept.cpp +++ b/srcs/webserv/accept.cpp @@ -18,7 +18,12 @@ void Webserv::_accept_connection(listen_socket &lsocket) _handle_last_signal(); return ; } - ::fcntl(accepted_fd, F_SETFL, O_NONBLOCK); + if (::fcntl(accepted_fd, F_SETFL, O_NONBLOCK) == -1) + { + std::perror("err fcntl()"); + if (::close(accepted_fd) == -1) + std::perror("err close()"); + } infos = _extract_infos(addr); Client new_client(accepted_fd, &lsocket, infos["port"], infos["ip"]); diff --git a/srcs/webserv/base.cpp b/srcs/webserv/base.cpp index cce34ac..94139c4 100644 --- a/srcs/webserv/base.cpp +++ b/srcs/webserv/base.cpp @@ -19,30 +19,6 @@ Webserv::Webserv() std::signal(SIGINT, signal_handler); } -/* Webserv::Webserv(Webserv const &src) -{ - -} */ - -// we'll come back to this -/* -Webserv::Webserv(std::vector* servers) -: _servers(servers) -{ - // talk to luke about what all this does - // the Param Constructor might need to do dif stuff - std::cout << "Server init\n"; - - _epfd = ::epoll_create1(0); // (EPOLL_CLOEXEC) for CGI fork ? - if (_epfd == -1) - { - std::perror("err epoll_create1(): "); - throw std::runtime_error("Epoll init"); - } -} -*/ - - Webserv::~Webserv() { close(_epfd); @@ -50,8 +26,3 @@ Webserv::~Webserv() _close_all_listen_sockets(); std::cerr << "Server destroyed\n"; } - -/* Webserv & Webserv::operator=(Webserv const &rhs) -{ - -} */ diff --git a/srcs/webserv/cgi.cpp b/srcs/webserv/cgi.cpp index 4adb7d1..7c5979c 100644 --- a/srcs/webserv/cgi.cpp +++ b/srcs/webserv/cgi.cpp @@ -101,7 +101,6 @@ void Webserv::_cgi_open_pipes(Client *client) void Webserv::_write_body_to_cgi(Client *client) { - std::cerr << "_write_body_to_cgi()"; // DEBUG ssize_t ret; std::string body = client->get_rq_body(); @@ -157,25 +156,24 @@ std::string Webserv::_dup_env(std::string var, int i) return (str); } -// TODO : verifier que les variables sont corrects /* https://www.rfc-editor.org/rfc/rfc3875#section-4.1 */ void Webserv::_set_env_vector(Client *client, std::vector &env_vector) { - env_vector.push_back(_dup_env("AUTH_TYPE")); // authentification not supporte + env_vector.push_back(_dup_env("AUTH_TYPE")); // authentification not supported env_vector.push_back(_dup_env("CONTENT_LENGTH" , client->get_rq_body().size())); env_vector.push_back(_dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type"))); env_vector.push_back(_dup_env("GATEWAY_INTERFACE" , "CGI/1.1")); // https://www.rfc-editor.org/rfc/rfc3875#section-4.1.4 - env_vector.push_back(_dup_env("PATH_INFO" , client->get_rq_script_info())); // LUKE: To Check - env_vector.push_back(_dup_env("PATH_TRANSLATED")); // not supported // LUKE: Why not supported ? + env_vector.push_back(_dup_env("PATH_INFO" , client->get_rq_script_info())); + env_vector.push_back(_dup_env("PATH_TRANSLATED")); // not used env_vector.push_back(_dup_env("QUERY_STRING" , client->get_rq_query())); env_vector.push_back(_dup_env("REMOTE_ADDR" , client->get_cl_ip())); env_vector.push_back(_dup_env("REMOTE_HOST" , client->get_cl_ip())); // equal to REMOTE_ADDR or empty env_vector.push_back(_dup_env("REMOTE_IDENT")); // authentification not supported env_vector.push_back(_dup_env("REMOTE_USER")); // authentification not supported env_vector.push_back(_dup_env("REQUEST_METHOD" , client->get_rq_method_str())); - env_vector.push_back(_dup_env("SCRIPT_NAME" , "/" + client->get_rq_script_path())); // LUKE: To Check + env_vector.push_back(_dup_env("SCRIPT_NAME" , "/" + client->get_rq_script_path())); env_vector.push_back(_dup_env("SERVER_NAME" , client->get_cl_lsocket()->host)); env_vector.push_back(_dup_env("SERVER_PORT" , client->get_cl_lsocket()->port)); env_vector.push_back(_dup_env("SERVER_PROTOCOL" , "HTTP/1.1")); @@ -279,15 +277,10 @@ void Webserv::_check_script_output(Client *client, std::string & output) _check_script_status(client, output); if (client->status >= 400 && client->status < 600) return; -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script status]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; client->status = _check_script_fields(output, client->status); -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script fields]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; _check_fields_duplicates(client, output); -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[fields duplicates]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; _remove_body_leading_empty_lines(output); -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script empty lines]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; _add_script_body_length_header(output); -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[script content length]:\n" << "client->status:[" << client->status << "]" RESET "\n"; ::print_special(output); std::cout << B_PURPLE "-----------" RESET "\n\n"; } void Webserv::_check_script_status(Client *client, std::string & output) @@ -424,4 +417,3 @@ void Webserv::_add_script_body_length_header(std::string & output) tmp += CRLF; output.insert(0, tmp); } - diff --git a/srcs/webserv/cgi_epoll.cpp b/srcs/webserv/cgi_epoll.cpp index 3220626..543e4bd 100644 --- a/srcs/webserv/cgi_epoll.cpp +++ b/srcs/webserv/cgi_epoll.cpp @@ -7,13 +7,8 @@ void Webserv::_read_cgi_output(Client *client) { char buf[BUFSIZE]; ssize_t ret; - std::cerr << "_read_cgi_output()" << "\n"; // Debug - std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; // Debug - std::cerr << "client fd = " << client->get_cl_fd() << "\n"; // Debug - std::cerr << "cgi fd = " << client->cgi_pipe_r_from_child << "\n"; // Debug ret = ::read(client->cgi_pipe_r_from_child, buf, BUFSIZE); - std::cerr << "cgi read ret = " << ret << "\n"; // Debug if (ret == -1) { std::perror("err read(cgi_fd)"); @@ -29,10 +24,6 @@ void Webserv::_read_cgi_output(Client *client) void Webserv::_handle_epollerr_cgi_output(uint32_t events, Client *client) { (void)events; - std::cerr << "cgi EPOLLERR" << "\n"; - std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; - std::cerr << "client fd = " << client->get_cl_fd() << "\n"; - std::cerr << "cgi fd = " << client->cgi_pipe_r_from_child << "\n"; client->status = 500; client->cgi_state = CGI_NO_CGI; @@ -40,7 +31,6 @@ void Webserv::_handle_epollerr_cgi_output(uint32_t events, Client *client) // Common with EPOLLHUP pid_t wait_ret; wait_ret = ::waitpid(client->cgi_pid, NULL, WNOHANG); - std::cerr << "cgi EPOLLERR waitpid ret = " << wait_ret << "\n"; if (wait_ret == client->cgi_pid) { _epoll_update(client->cgi_pipe_r_from_child, 0, EPOLL_CTL_DEL); @@ -55,17 +45,10 @@ void Webserv::_handle_epollerr_cgi_output(uint32_t events, Client *client) void Webserv::_handle_epollhup_cgi_output(uint32_t events, Client *client) { (void)events; - (void)client; - -/* std::cerr << "cgi EPOLLHUP" << "\n"; - std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; - std::cerr << "client fd = " << client->get_cl_fd() << "\n"; - std::cerr << "cgi fd = " << client->cgi_pipe_r_from_child << "\n"; */ // Common with EPOLLERR pid_t wait_ret; wait_ret = ::waitpid(client->cgi_pid, NULL, WNOHANG); - // std::cerr << "cgi EPOLLHUP waitpid ret = " << wait_ret << "\n"; if (wait_ret == client->cgi_pid) { _epoll_update(client->cgi_pipe_r_from_child, 0, EPOLL_CTL_DEL); diff --git a/srcs/webserv/close.cpp b/srcs/webserv/close.cpp index 5871980..a3102dc 100644 --- a/srcs/webserv/close.cpp +++ b/srcs/webserv/close.cpp @@ -9,12 +9,10 @@ void Webserv::_close_client(int fd) { if (*it == fd) { - // _epoll_update(fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG std::cerr << "close client fd " << fd << "\n"; if (::close(fd) == -1) std::perror("err close()"); _close_client_cgi_pipes(&(*it)); - // it->clear(); // PISTE, debug normalement superflu _clients.erase(it); break; } @@ -48,15 +46,7 @@ void Webserv::_close_client_cgi_pipes(Client *client) void Webserv::_close_all_clients() { _close_all_clients_fd(); - _clients.clear(); - // REMPLACEMENT -> -/* while (!_clients.empty()) - { - std::cerr << "_clients.pop_back() " << &_clients.back() << "\n"; - _clients.back().clear(); - _clients.pop_back(); - } */ } void Webserv::_close_all_clients_fd() @@ -66,7 +56,6 @@ void Webserv::_close_all_clients_fd() std::vector::iterator it_end = _clients.end(); while (it != it_end) { - // _epoll_update(_clients.back().fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG std::cerr << "close client fd " << it->get_cl_fd() << "\n"; if (::close(it->get_cl_fd()) == -1) std::perror("err close()"); @@ -80,7 +69,6 @@ void Webserv::_close_all_clients_cgi_pipes() std::vector::iterator it_end = _clients.end(); while (it != it_end) { - // _epoll_update(_clients.back().fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG _close_client_cgi_pipes(&(*it)); ++it; } @@ -91,7 +79,6 @@ void Webserv::_close_all_listen_sockets() { // TODO : change like clients (clear in place of pop_back) while (!_listen_sockets.empty()) { - // _epoll_update(_listen_sockets.back().fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG std::cerr << "close lsocket fd " << _listen_sockets.back().fd << "\n"; if (::close(_listen_sockets.back().fd) == -1) std::perror("err close()"); @@ -99,11 +86,11 @@ void Webserv::_close_all_listen_sockets() } } -void Webserv::_reopen_lsocket(std::vector::iterator it) -{ /* ** Many common code with init_virtual_servers(). Could refactor it. */ +void Webserv::_reopen_lsocket(std::vector::iterator it) +{ int ret; std::cerr << "close lsocket " << it->fd << "\n"; @@ -119,9 +106,8 @@ void Webserv::_reopen_lsocket(std::vector::iterator it) } it->fd = ret; - // HUGO ADD + // From : https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select // allow socket descriptor to be reuseable - // I just copied it from https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select int on = 1; if (setsockopt(it->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { @@ -129,7 +115,6 @@ void Webserv::_reopen_lsocket(std::vector::iterator it) _listen_sockets.erase(it); return; } - // HUGO ADD END try { _bind(it->fd, std::strtoul(it->port.c_str(), NULL, 10), it->host); @@ -164,8 +149,5 @@ void Webserv::_handle_epoll_error_client(uint32_t events, int fd) std::cerr << "EPOLLERR on client fd " << fd << "\n"; // DEBUG if (events & EPOLLHUP) std::cerr << "EPOLLHUP on client fd " << fd << "\n"; // DEBUG - if (std::find(_clients.begin(), _clients.end(), fd) != _clients.end()) - std::cerr << "Found the client in _clients" << "\n"; // DEBUG - - _close_client(fd); // " EPOLLHUP on client fd 8 " en boucle quand on mattraque un peu les CGI, donc il ne le trouve pas dans _clients. Etrange. + _close_client(fd); } diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index 3bc27ec..91d53ff 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -35,18 +35,14 @@ void Webserv::init_virtual_servers(std::vector* servers) new_socket.port = it->port; _listen_sockets.push_back(new_socket); - // HUGO ADD - // + // From : https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select // allow socket descriptor to be reuseable - // I just copied it from https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select int on = 1; - if (setsockopt(new_socket.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + if (setsockopt(new_socket.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { ::perror("err setsockopt()"); throw std::runtime_error("Socket init"); } - // - // HUGO ADD END _bind(new_socket.fd, std::strtoul(it->port.c_str(), NULL, 10), it->host); _listen(new_socket.fd, 42); // 42 arbitrary @@ -69,7 +65,6 @@ void Webserv::_bind(int socket_fd, in_port_t port, std::string host) addr.sin_family = AF_INET; addr.sin_port = ::htons(port); addr.sin_addr.s_addr = ::htonl(::inet_addr(host.c_str())); - // addr.sin_addr.s_addr = ::htonl(INADDR_ANY); // htonl useless with 0 value (INADDR_ANY) ? if (::bind(socket_fd, (const sockaddr*)&addr, sizeof addr) == -1) { diff --git a/srcs/webserv/method_get.cpp b/srcs/webserv/method_get.cpp index 5090252..2543ee2 100644 --- a/srcs/webserv/method_get.cpp +++ b/srcs/webserv/method_get.cpp @@ -2,7 +2,6 @@ #include "Webserv.hpp" #define MAX_FILESIZE 1 * MB // unused -// const? /* https://www.rfc-editor.org/rfc/rfc9110.html#name-get */ @@ -84,7 +83,11 @@ if (size > MAX_FILESIZE) */ -// const? +/* + nginx.org.
+ index1.html + .. +*/ void Webserv::_autoindex(Client *client, const std::string &path) { std::cout << "_autoindex()\n"; @@ -93,7 +96,6 @@ void Webserv::_autoindex(Client *client, const std::string &path) DIR *dir; struct dirent *ent; - // std::cout << "Path in auto is: " << path << '\n'; if ( (dir = opendir(path.c_str()) ) != NULL) { dir_list.append(AUTOINDEX_START); @@ -117,13 +119,6 @@ void Webserv::_autoindex(Client *client, const std::string &path) dir_list.append(""); dir_list.append("\n"); } - -// nginx.org.
-// index1.html - -// apparently this is more than good enough! -// .. - dir_list.append(AUTOINDEX_END); closedir (dir); client->status = 200; diff --git a/srcs/webserv/method_post.cpp b/srcs/webserv/method_post.cpp index 3c152db..8f576ef 100644 --- a/srcs/webserv/method_post.cpp +++ b/srcs/webserv/method_post.cpp @@ -8,16 +8,14 @@ void Webserv::_post(Client *client, const std::string &path) { (void)path; // unused, we use "assigned_location->upload_dir" instead std::cout << "_post()\n"; - std::cerr << "upload_dir = " << client->assigned_location->upload_dir << "\n"; - if (client->get_rq_abs_path() != client->assigned_location->path) - client->status = 404; // 404 ? J'ai un doute. + client->status = 404; // 404 or other status better ? else if (client->assigned_location->upload_dir.empty()) - client->status = 404; // 404 ? J'ai un doute. + client->status = 404; // 404 or other status better ? else if (client->get_rq_multi_bodys().empty()) { - client->status = 415; + client->status = 415; // Unsupported Media Type client->response.append("Accept: multipart/form-data"); // empty, no encoding accepted client->response.append(CRLF); } @@ -25,7 +23,7 @@ void Webserv::_post(Client *client, const std::string &path) _upload_files(client); } -// #include // could add date to DEFAULT_NAME to avoid overwriting files +// #include // TODO: could add date to DEFAULT_NAME to avoid overwriting files #define DEFAULT_NAME "unnamed_file" void Webserv::_upload_files(Client *client) { @@ -58,7 +56,7 @@ void Webserv::_upload_files(Client *client) { filename = filename.substr(pos + sizeof("filename=")-1); std::cerr << "filename ="<< filename << "\n"; - // A l'arrache pour enlever les " + // Pour enlever les " filename.erase(0, 1); std::cerr << "filename ="<< filename << "\n"; filename.erase(filename.size()-1, 1); @@ -69,7 +67,7 @@ void Webserv::_upload_files(Client *client) filename = DEFAULT_NAME + ::itos(i_name++); std::cerr << "filename ="<< filename << "\n"; - path = client->assigned_location->upload_dir; // Assume there a final '/' + path = client->assigned_location->upload_dir; path.append(filename); @@ -78,7 +76,6 @@ void Webserv::_upload_files(Client *client) else file_existed = true; - // How to determine status 403 for file that dont already exist ? access() on the upload_dir ? if (file_existed && ::access(path.c_str(), W_OK) == -1) { std::perror("err access()"); diff --git a/srcs/webserv/request.cpp b/srcs/webserv/request.cpp index 9df7a75..7c2cedd 100644 --- a/srcs/webserv/request.cpp +++ b/srcs/webserv/request.cpp @@ -36,22 +36,15 @@ int Webserv::_read_request(Client *client) ssize_t ret; ret = ::recv(client->get_cl_fd(), buf, BUFSIZE, 0); - std::cerr << "recv() on fd(" << client->get_cl_fd() << ") returned = " << ret << "\n" ; + std::cerr << "recv() on fd(" << client->get_cl_fd() << ") ret = " << ret << "\n" ; if (ret == -1) { std::perror("err recv()"); return READ_CLOSE; } if (ret == 0) - { - std::cerr << "recv() read 0, then close client" << "\n"; // DEBUG return READ_CLOSE; - } client->raw_request.append(buf, ret); - // ::print_special(client->raw_request); - // std::cerr << "__raw_request__\n" << client->raw_request << "\n______\n"; // DEBUG - - // print_special(client->raw_request); if (!client->header_complete) { @@ -73,7 +66,6 @@ int Webserv::_read_request(Client *client) } if (client->header_complete) { - // client->read_body_size += ret; // Not accurate, part of body could have been read with headers, unused for now client->parse_request_body(); if (client->status || client->body_complete) return READ_COMPLETE; diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index d000481..ef1d10a 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -22,10 +22,9 @@ void Webserv::_response(Client *client) else if (ret == SEND_COMPLETE) { if (client->get_rq_headers("Connection") == "close" - || client->status == 400 // TODO: Refactoring + || client->status == 400 || client->status == 408 || client->status == 413) - // || client->cgi_state == CGI_OUTPUT_COMPLETE) // DEBUG _close_client(client->get_cl_fd()); else { @@ -42,9 +41,7 @@ int Webserv::_send_response(Client *client) std::cerr << "send()\n"; if (client->response.empty()) - { _append_base_headers(client); - } if (!client->status) { @@ -58,34 +55,27 @@ int Webserv::_send_response(Client *client) if (client->status >= 400) _error_html_response(client); -// /*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output + headers]:" RESET "\n"; ::print_special(client->response); std::cout << "\n" B_PURPLE "-----------" RESET "\n\n"; - - // /* Debug */ std::cerr << "client->response.size() = " << client->response.size() << "\n"; // DEBUG ret = ::send(client->get_cl_fd(), client->response.c_str(), client->response.size(), 0); if (ret == -1) { std::perror("err send()"); - std::cerr << "client.fd =" << client->get_cl_fd() << "\n"; // DEBUG return SEND_CLOSE; } - if (ret == 0) // actually never happen ? + if (ret == 0) { - std::cerr << "SEND RET 0 for client.fd =" << client->get_cl_fd() << "\n"; // DEBUG + std::cerr << "send() ret == 0 never happens ?" << "\n"; // Debug return SEND_CLOSE; } - // /* Debug */ std::cerr << "ret send() = " << ret << "\n"; // DEBUG return SEND_COMPLETE; } void Webserv::_append_base_headers(Client *client) { - std::cerr << "_append_base_headers()\n"; // debug - client->response.append("Server: Webserv/0.1" CRLF); if (client->get_rq_headers("Connection") == "close" - || client->status == 400 // TODO: Refactoring + || client->status == 400 || client->status == 408 || client->status == 413) client->response.append("Connection: close" CRLF); @@ -97,7 +87,7 @@ void Webserv::_construct_response(Client *client) { std::string path; std::string script_output; - + path = _replace_url_root(client, client->get_rq_abs_path()); if (client->cgi_state == CGI_READY_TO_EXEC) { @@ -108,13 +98,9 @@ void Webserv::_construct_response(Client *client) } else if (client->cgi_state == CGI_OUTPUT_COMPLETE) { - // /*DEBUG*/ std::cout << "\n" B_PURPLE "[response]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; - // /*DEBUG*/ std::cout << "\n" B_PURPLE "[script output]:" RESET "\n"; ::print_special(client->cgi_output); std::cout << B_PURPLE "-----------" RESET "\n\n"; - _check_script_output(client, client->cgi_output); // FD_CGI : adjust for client->cgi_output; + _check_script_output(client, client->cgi_output); if (client->status < 400 || client->status >= 600) client->response += client->cgi_output; - // client->cgi_state = CGI_NO_CGI; // Not indispensable, reset when client.clear() - // /*DEBUG*/ std::cout << "\n" B_PURPLE "[response + output]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; } else if (_is_cgi(client, path)) _cgi_open_pipes(client); @@ -124,9 +110,6 @@ void Webserv::_construct_response(Client *client) void Webserv::_process_method(Client *client, std::string &path) { -// std::cerr << "allow_methods = " << http_methods_to_str(client->assigned_location->allow_methods) << "\n"; // debug - std::cerr << "Path again: " << path << '\n'; // debug - switch (client->get_rq_method()) { case (GET): @@ -142,13 +125,10 @@ void Webserv::_process_method(Client *client, std::string &path) std::string Webserv::_replace_url_root(Client *client, std::string path) { - // /* Debug */ std::cerr << "assigned_location->path = " << client->assigned_location->path << "\n"; // debug - // /* Debug */ std::cerr << "path before = " << path << "\n"; // DEBUG if (client->assigned_location->path == "/") path.insert(0, client->assigned_location->root); else path.replace(0, client->assigned_location->path.size(), client->assigned_location->root); - // /* Debug */ std::cerr << "path after = " << path << "\n"; // DEBUG return path; } @@ -212,4 +192,3 @@ void Webserv::_append_body(Client *client, const std::string &body, const std::s client->response.append(CRLF); client->response.append(body); } - diff --git a/srcs/webserv/run_loop.cpp b/srcs/webserv/run_loop.cpp index d62856f..f0751d6 100644 --- a/srcs/webserv/run_loop.cpp +++ b/srcs/webserv/run_loop.cpp @@ -16,6 +16,8 @@ void Webserv::run() Client *client_cgi_input = NULL; Client *client_cgi_output = NULL; + std::signal(SIGPIPE, signal_handler); + std::signal(SIGINT, signal_handler); g_run = true; while (g_run) { @@ -29,7 +31,11 @@ void Webserv::run() if (errno_copy == EINTR) g_run = false; else + { + std::signal(SIGPIPE, SIG_DFL); + std::signal(SIGINT, SIG_DFL); throw std::runtime_error("Epoll wait"); + } } else if (nfds == 0 && !_clients.empty()) _timeout(); @@ -101,4 +107,6 @@ void Webserv::run() } } } + std::signal(SIGPIPE, SIG_DFL); + std::signal(SIGINT, SIG_DFL); } diff --git a/srcs/webserv/signal.cpp b/srcs/webserv/signal.cpp index 1074f26..204cd78 100644 --- a/srcs/webserv/signal.cpp +++ b/srcs/webserv/signal.cpp @@ -14,16 +14,10 @@ void Webserv::_handle_last_signal() if (g_last_signal == SIGPIPE) { std::cerr << "SIGPIPE\n"; - // if (_actual_client) - // { - // _close_client(_actual_client->fd); - // _actual_client = NULL; - // } } else if (g_last_signal == SIGINT) { g_run = false; - // maybe a throw here instead of "g_run" ? } g_last_signal = 0; } diff --git a/srcs/webserv/timeout.cpp b/srcs/webserv/timeout.cpp index d3f3561..9bd3e8c 100644 --- a/srcs/webserv/timeout.cpp +++ b/srcs/webserv/timeout.cpp @@ -12,12 +12,7 @@ void Webserv::_timeout() std::cerr << "timeout request fd " << it->get_cl_fd() << "\n"; it->status = 408; _epoll_update(it->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD); - - // DEBUG, close without repsonse 408 - /* _close_client(it->get_cl_fd()); - it = _clients.begin(); */ } - // else // DEBUG ++it; } }