From 8f167d85f340198eff7e2ccd89c976c9c737f9bb Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Tue, 2 Aug 2022 21:11:54 +0200 Subject: [PATCH] wip integration of client.request and ServerConfig + Client get return reference + wip binary flags for http_method + moved config parser files --- Makefile | 7 +- memo.txt | 13 ++- srcs/Client.cpp | 10 +-- srcs/Client.hpp | 11 +-- srcs/{ => config}/ConfigParser.cpp | 6 +- srcs/{ => config}/ConfigParser.hpp | 0 srcs/{ => config}/ConfigParserPost.cpp | 0 srcs/{ => config}/ConfigParserUtils.cpp | 0 srcs/{ => config}/LocationConfig.hpp | 0 srcs/{ => config}/ServerConfig.hpp | 0 srcs/utils.hpp | 14 +++- srcs/webserv/Webserv.hpp | 11 +-- srcs/webserv/close.cpp | 2 +- srcs/webserv/response.cpp | 103 ++++++++++++++---------- 14 files changed, 107 insertions(+), 70 deletions(-) rename srcs/{ => config}/ConfigParser.cpp (99%) rename srcs/{ => config}/ConfigParser.hpp (100%) rename srcs/{ => config}/ConfigParserPost.cpp (100%) rename srcs/{ => config}/ConfigParserUtils.cpp (100%) rename srcs/{ => config}/LocationConfig.hpp (100%) rename srcs/{ => config}/ServerConfig.hpp (100%) diff --git a/Makefile b/Makefile index 221d18b..ad045bd 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,13 @@ CXXFLAGS += -MMD -MP #header dependencie VPATH = $(SRCS_D) HEADERS_D = srcs \ - srcs/webserv + srcs/webserv \ + srcs/config SRCS_D = srcs \ - srcs/webserv + srcs/webserv \ + srcs/config + SRCS = main.cpp \ base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \ accept.cpp request.cpp response.cpp \ diff --git a/memo.txt b/memo.txt index 6f8b3ab..5482d1f 100644 --- a/memo.txt +++ b/memo.txt @@ -1,7 +1,14 @@ -- un thread par serveur présent dans le fichier de config ? ----------------- ----------------- +- http_method en mode binary flags. "std::vector allow_methods" -> "unsigned int allow_methods;" +- Dans le parsing, trier les "locations" par ordre de precision. +Compter les "/" dans le chemin, les locations avec le plus de "/" seront en premier dans le vector. +- Il faut vérifier le path de la requête, voir si le serveur est bien censé délivrer cette ressource et si le client y a accès, avant d'appeler le CGI. + + +__________________________ +-------------------------- + +----Discord 42------------ Un truc cool et surtout bien utile ici c'est d'utiliser un proxy entre ton navigateur et ton serveur pour vérifier ce qui est envoyé en raw. Les navigateurs peuvent avoir des comportements différents. Vous avez des modules sur vos navigateur ou des logiciels externe. C'est assez rapide et gratuit. \ No newline at end of file diff --git a/srcs/Client.cpp b/srcs/Client.cpp index db3e2c8..5551a1f 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -49,11 +49,11 @@ void Client::parse_request() -std::string Client::get_method() { return _request.method; } -std::string Client::get_path() { return _request.path; } -std::string Client::get_version() { return _request.version; } -std::string Client::get_body() { return _request.body; } -std::string Client::get_headers(std::string key) { return _request.headers[key]; } +std::string &Client::get_method() { return _request.method; } +std::string &Client::get_path() { return _request.path; } +std::string &Client::get_version() { return _request.version; } +std::string &Client::get_body() { return _request.body; } +std::string &Client::get_headers(const std::string &key) { return _request.headers[key]; } /********************************************* * PRIVATE MEMBER FUNCTIONS diff --git a/srcs/Client.hpp b/srcs/Client.hpp index 002f1c5..24a6c9c 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -30,11 +30,12 @@ class Client std::string response; unsigned int status; - std::string get_method(); - std::string get_path(); - std::string get_version(); - std::string get_body(); - std::string get_headers(std::string key); + // const functions ? + std::string &get_method(); + std::string &get_path(); + std::string &get_version(); + std::string &get_body(); + std::string &get_headers(const std::string &key); void parse_request(); diff --git a/srcs/ConfigParser.cpp b/srcs/config/ConfigParser.cpp similarity index 99% rename from srcs/ConfigParser.cpp rename to srcs/config/ConfigParser.cpp index c63326b..69ab9d0 100644 --- a/srcs/ConfigParser.cpp +++ b/srcs/config/ConfigParser.cpp @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/07/13 22:11:17 by me #+# #+# */ -/* Updated: 2022/08/02 14:05:03 by lperrey ### ########.fr */ +/* Updated: 2022/08/02 19:21:49 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -263,7 +263,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, \ for (unsigned long i = 0; i != tmp_val.size(); i++) { http_method m = _str_to_method_type(tmp_val[i]); - if (m == 3) + if (m == INVALID) throw std::invalid_argument("not a valid method"); server->allow_methods.push_back(m); } @@ -348,7 +348,7 @@ void ConfigParser::_set_location_values(LocationConfig *location, \ for (unsigned long i = 0; i != tmp_val.size(); i++) { http_method m = _str_to_method_type(tmp_val[i]); - if (m == 3) + if (m == INVALID) throw std::invalid_argument("not a valid method"); location->allow_methods.push_back(m); } diff --git a/srcs/ConfigParser.hpp b/srcs/config/ConfigParser.hpp similarity index 100% rename from srcs/ConfigParser.hpp rename to srcs/config/ConfigParser.hpp diff --git a/srcs/ConfigParserPost.cpp b/srcs/config/ConfigParserPost.cpp similarity index 100% rename from srcs/ConfigParserPost.cpp rename to srcs/config/ConfigParserPost.cpp diff --git a/srcs/ConfigParserUtils.cpp b/srcs/config/ConfigParserUtils.cpp similarity index 100% rename from srcs/ConfigParserUtils.cpp rename to srcs/config/ConfigParserUtils.cpp diff --git a/srcs/LocationConfig.hpp b/srcs/config/LocationConfig.hpp similarity index 100% rename from srcs/LocationConfig.hpp rename to srcs/config/LocationConfig.hpp diff --git a/srcs/ServerConfig.hpp b/srcs/config/ServerConfig.hpp similarity index 100% rename from srcs/ServerConfig.hpp rename to srcs/config/ServerConfig.hpp diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 70b16c5..6df52cb 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -7,12 +7,20 @@ # include # include // atoi +// enum http_method +// { +// GET = 0b000001, +// POST = 0b000010, +// DELETE = 0b000100, +// INVALID = 0b001000, +// }; + enum http_method { GET = 1, - POST, - DELETE, - INVALID, + POST = 1 << 1, + DELETE = 1 << 2, + INVALID = 1 << 3, }; std::vector split(std::string input, char delimiter); diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 193b57d..7a1715c 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -22,7 +22,7 @@ // # include // usefull for what ? -> 'man (7) ip' says it's a superset of 'netinet/in.h' # include // find # include // string -# include // perror +# include // perror, remove # include // atoi (athough it's already cover by ) # include "Client.hpp" @@ -68,10 +68,11 @@ class Webserv void _read_request(Client *client); // response.cpp void _response(Client *client); - void _send_response(Client *client); - void _construct_response(Client *client); - void _insert_status_line(Client *client); - void _get_ressource(Client *client); + ServerConfig &_determine_process_server(Client *client); + void _send_response(Client *client, ServerConfig &server); + void _construct_response(Client *client, ServerConfig &server); + void _insert_status_line(Client *client, ServerConfig &server); + void _get_ressource(Client *client, ServerConfig &server); // cgi_script.cpp bool _is_cgi(Client *client); void _exec_cgi(Client *client); diff --git a/srcs/webserv/close.cpp b/srcs/webserv/close.cpp index f4bc0b9..70a1e3f 100644 --- a/srcs/webserv/close.cpp +++ b/srcs/webserv/close.cpp @@ -6,7 +6,7 @@ void Webserv::_close_client(int fd) std::vector::iterator it = _clients.begin(); while (it != _clients.end()) { - if (it->fd == fd) + if (*it == fd) { // _epoll_update(fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG if (::close(fd) == -1) diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 0e97c6c..0f4373f 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -3,25 +3,48 @@ void Webserv::_response(Client *client) { - _send_response(client); + ServerConfig &server = _determine_process_server(client); + _send_response(client, server); if (g_last_signal) _handle_last_signal(); } -void Webserv::_send_response(Client *client) +ServerConfig &Webserv::_determine_process_server(Client *client) +{ +/* + TODO : determine virtual server based on ip_address::port and server_name + Ior now its just based on server_name. + (maybe with a map< string, std::vector > where the string is "ip_adress::port") + http://nginx.org/en/docs/http/request_processing.html +*/ + + std::string &server_name = client->get_headers("Host"); + std::vector::iterator it = _servers.begin(); + while (it != _servers.end()) + { + if ( std::find(it->server_name.begin(), it->server_name.end(), server_name) != it->server_name.end() ) + break; + ++it; + } + if (it != _servers.end()) + return (*it); + else + return (_servers.front()); +} + +void Webserv::_send_response(Client *client, ServerConfig &server) { ssize_t ret; std::cerr << "send()\n"; - std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; // DEBUG + // std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; // DEBUG - _construct_response(client); + _construct_response(client, server); - ret = ::send(client->fd, client->response.data(), client->response.size(), 0); + ret = ::send(client->fd, client->response.c_str(), client->response.size(), 0); if (ret == -1) { std::perror("err send()"); - std::cerr << "client ptr =" << client << "\n"; // DEBUG std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG _close_client(client->fd); return ; @@ -37,25 +60,29 @@ void Webserv::_send_response(Client *client) } } -void Webserv::_construct_response(Client *client) +void Webserv::_construct_response(Client *client, ServerConfig &server) { client->status = 200; client->response.append("Server: Webserv/0.1\r\n"); - if (client->raw_request.find("Connection: close") != std::string::npos) + if (client->get_headers("Connection") == "close") client->response.append("Connection: close\r\n"); else client->response.append("Connection: keep-alive\r\n"); - _get_ressource(client); + // TODO : Method switch (GET, POST, DELETE) + _get_ressource(client, server); - _insert_status_line(client); + _insert_status_line(client, server); } -#define E400 "\r\n400 Bad Request

400 Bad Request


Le Webserv/0.1

" -#define E404 "\r\n404 Not Found

404 Not Found


Le Webserv/0.1

" -#define E500 "\r\n500 Internal Server Error

500 Internal Server Error


Le Webserv/0.1

" -void Webserv::_insert_status_line(Client *client) +// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml +#define HTML_ERROR(STATUS) "\r\n"STATUS"

"STATUS"


Le Webserv/0.1

" +#define S200 "200 OK" +#define S400 "400 Bad Request" +#define S404 "404 Not Found" +#define S500 "500 Internal Server Error" +void Webserv::_insert_status_line(Client *client, ServerConfig &server) { std::string status_line; @@ -64,19 +91,19 @@ void Webserv::_insert_status_line(Client *client) switch (client->status) { case (200): - status_line.append("200 OK"); + status_line.append(S200); break; case (400): - status_line.append("400 Not Found"); - client->response.append(E400); + status_line.append(S400); + client->response.append(HTML_ERROR(S400)); break; case (404): - status_line.append("404 Not Found"); - client->response.append(E404); + status_line.append(S404); + client->response.append(HTML_ERROR(S404)); break; case (500): - status_line.append("500 Internal Server Error"); - client->response.append(E500); + status_line.append(S500); + client->response.append(HTML_ERROR(S500)); break; } status_line.append("\r\n"); @@ -87,11 +114,18 @@ void Webserv::_insert_status_line(Client *client) #define ROOT "www" #define INDEX "index.html" #define MAX_FILESIZE 1000000 // (1Mo) -void Webserv::_get_ressource(Client *client) +void Webserv::_get_ressource(Client *client, ServerConfig &server) { std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ? char buf[MAX_FILESIZE+1]; std::string tmp; + std::string path = client->get_path(); + + if (path == "/") // TODO ; With server config + path.append(INDEX); + path.insert(0, ROOT); + + std::cerr << "path = " << path << "\n"; // TMP HUGO // @@ -103,32 +137,15 @@ void Webserv::_get_ressource(Client *client) // // END TMP HUGO - // Mini parsing à l'arrache du PATH - std::string path; - try - { - path = client->raw_request.substr(0, client->raw_request.find("\r\n")); - path = path.substr(0, path.rfind(" ")); - path = path.substr(path.find("/")); - if (path == "/") - path.append(INDEX); - path.insert(0, ROOT); - } - catch (std::out_of_range& e) - { - std::cout << e.what() << '\n'; - client->status = 400; - return ; - } - - if (access(path.data(), R_OK) == -1) + + if (access(path.c_str(), R_OK) == -1) { std::perror("err access()"); client->status = 404; return ; } - ifd.open(path.data(), std::ios::binary | std::ios::ate); // std::ios::binary (binary for files like images ?) + ifd.open(path.c_str(), std::ios::binary | std::ios::ate); // std::ios::binary (binary for files like images ?) if (!ifd) { std::cerr << path << ": open fail" << '\n'; @@ -151,7 +168,7 @@ void Webserv::_get_ressource(Client *client) ifd.read(buf, size); buf[ifd.gcount()] = '\0'; - client->response.append("Content-Type: text/html; charset=UTF-8\r\n"); + client->response.append("Content-Type: text/html; charset=UTF-8\r\n"); // TODO : determine Content-Type client->response.append("Content-Length: ");