diff --git a/README.md b/README.md index e5748b5..ac9034c 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,36 @@ -## questions : +## work together +#### questions - in client.cpp i fill the port, is there a default one in case it's not in the request ? -- le cgi-script doit renvoyer au moins un header suivit d'une ligne vide -- ce header est soit "Content-Type", soit "Location", soit "Status" -- il peut dans certains cas envoyer d'autres headers -- le serveur doit verifier qu'il n'y a pas de doublons dans les headers -- le serveur doit verifier le formatage des headers (typiquement l'encodage, par exemple pour les newlines) -- ? comment on passe le body-message au script ? section 4.2 - -> en ecrivant le body dans le fd temp sur lequel on a branché stdin et stdout avant d'execve le script -- ? on doit gerer l'authentification ? - -> pas pour l'instant on va dire :p -- ? pourquoi on construit un script-cgi ? section 3.3 -- ? on doit gerer l'authentification ? -- ? pourquoi on doit construire un script-cgi ? section 3.3 -- ? si l'uri correspond au script-cgi, ca appel le script donc ? section 3.3 +#### notifications +- i changed the Client getters in two categories : + - getters for requests infos : `get_rq_` + - getters for client sides infos : `get_cl_` (such as ip of client) +- i changed the variables in request struct in Client : + - `path` become `uri` (ex. /path/to/file?var=val) + - add `abs_path` (ex. /path/to/file ) + - add `query` (ex. var=val) +- the header fields names, as key in map, are stored in lowercase, and getters are case-insensitives + +#### share knowledge +##### cgi +- the cgi-script will send back at least one header field followed by an empty line +- this header field will be one of three : + - "Content-Type" + - "Location" + - "Status" +- the cgi-script may send back more header fields +- the server must check and modify few things : + - there is no duplicate in headers fields (if there is, resolve conflict) + - there is no space between the field name and the ":" + - the newlines are of form "\r\n", and not "\n" only + - if the location field is not present, then if the status field is not present either, then the status code is 200 + - the cgi-script can return a location field, of two types : + - local redirection : start with a "/", the server must answer as if this was the request uri + - client redirection : start with ":", the server must send back a status 302 with this uri to the client +- to pass the body-message to the cgi-script, we write it into the temporary fd on which the script read it's standard input + --- ## man @@ -141,10 +157,12 @@ - local redirect response : - it must return only a Location field - it contains a local path URI and query string ('local-pathquery') + - the local path URI must start with a "/" - the server must generate the response for this local-pathquery - client redirect response : - it must return only a Location field - it contains an absolute URI path, to indicate the client that it should reprocess the request with this URI + - the absolute URI always start with the name of scheme followed by ":" - the http server must generate a 302 'Found' message - client redirect response with document - it must return a Location field with an absolute URI path diff --git a/srcs/Client.cpp b/srcs/Client.cpp index b96b924..94dc5ae 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -74,6 +74,7 @@ void Client::parse_request() std::vector list; size_t pos; +// DEBUG std::cout << "\n" << "request:\n" << raw_request << "START _______________________\n\n" @@ -87,7 +88,7 @@ std::cout << "\n" list.erase(list.begin()); _parse_request_headers(list); _parse_request_body(pos + 4); - _parse_port_hostname(_request.headers["Host"]); + _parse_port_hostname(this->get_rq_headers("Host")); // add "raw_request.clear()" after parsing ? for little less memory usage ? } @@ -103,10 +104,14 @@ void Client::clear() void Client::clear_request() { _request.method = UNKNOWN; - _request.path.clear(); + _request.uri.clear(); _request.version.clear(); _request.headers.clear(); _request.body.clear(); + _request.abs_path.clear(); + _request.query.clear(); + _request.port.clear(); + _request.hostname.clear(); } @@ -115,25 +120,24 @@ void Client::clear_request() *********************************************/ // client side -int Client::get_cl_fd() const { return _fd; } +int Client::get_cl_fd() const { return _fd; } std::string Client::get_cl_ip() const { return _ip; } listen_socket * Client::get_cl_lsocket() const { return _lsocket; } std::string Client::get_cl_port() const { return _port; } + // requette -http_method Client::get_rq_method()const { return _request.method; } +http_method Client::get_rq_method() const { return _request.method; } std::string Client::get_rq_method_str() const -{ - std::string method; - method = ::http_methods_to_str(_request.method); - return method; -} -std::string Client::get_rq_path() const { return _request.path; } + { return ::http_methods_to_str(_request.method); } +std::string Client::get_rq_uri() const { return _request.uri; } +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_headers(const std::string & key) - { return _request.headers[key]; } +std::string Client::get_rq_headers(const std::string & key) const + { return _request.headers.find(::str_tolower(key))->second; } /********************************************* @@ -160,13 +164,26 @@ void Client::_parse_request_line( std::string rline ) // https://stackoverflow.com/questions/40311306/when-is-absoluteuri-used-from-the-http-request-specs tmp = ::trim(sline[1], ' '); tmp = ::trim(tmp, '\r'); - _request.path = tmp; + _request.uri = tmp; + _parse_request_uri( tmp ); // http version tmp = ::trim(sline[2], ' '); tmp = ::trim(tmp, '\r'); _request.version = tmp; } +void Client::_parse_request_uri( std::string uri ) +{ + size_t pos; + + pos = uri.find("?"); + if (pos != std::string::npos) + _request.query = uri.substr(pos + 1); + else + _request.query = ""; + _request.abs_path = uri.substr(0, pos); +} + void Client::_parse_request_headers( std::vector list ) { std::string key; @@ -180,6 +197,7 @@ void Client::_parse_request_headers( std::vector list ) key = (*it).substr( 0, pos ); key = ::trim(key, ' '); key = ::trim(key, '\r'); + key = ::str_tolower(key); val = (*it).substr( pos + 1 ); val = ::trim(val, ' '); val = ::trim(val, '\r'); diff --git a/srcs/Client.hpp b/srcs/Client.hpp index b2c11ae..65340a1 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -14,7 +14,9 @@ struct Request { http_method method; - std::string path; + std::string uri; + std::string abs_path; + std::string query; std::string version; std::map headers; std::string body; @@ -38,10 +40,6 @@ class Client size_t body_size; unsigned int status; -// std::string port; -// std::string ip; -// listen_socket * lsocket; - // getters int get_cl_fd() const; std::string get_cl_port() const; @@ -51,12 +49,14 @@ class Client // requests getters http_method get_rq_method() const; std::string get_rq_method_str() const; - std::string get_rq_path() const; + std::string get_rq_uri() const; + std::string get_rq_abs_path() const; + 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_headers(const std::string & key); + std::string get_rq_headers(const std::string & key) const; void parse_request(); void clear(); @@ -70,6 +70,7 @@ class Client struct Request _request; void _parse_request_line( std::string rline ); + void _parse_request_uri( std::string uri ); void _parse_request_headers( std::vector list ); void _parse_request_body( size_t pos ); void _parse_port_hostname(std::string host); @@ -81,3 +82,4 @@ bool operator==(const Client& lhs, int fd); bool operator==(int fd, const Client& rhs); #endif + diff --git a/srcs/utils.cpp b/srcs/utils.cpp index 2144a51..dbd2833 100644 --- a/srcs/utils.cpp +++ b/srcs/utils.cpp @@ -105,3 +105,10 @@ bool operator==(const listen_socket& lhs, int fd) bool operator==(int fd, const listen_socket& rhs) { return fd == rhs.fd; } + +std::string str_tolower(std::string str) +{ + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return str; +} + diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 6ea657c..5b271b4 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -6,6 +6,8 @@ # include # include # include // atoi +# include // tolower +# include // transform # define CR "\r" # define LF "\n" @@ -46,5 +48,6 @@ std::string trim(std::string str, char c); http_method str_to_http_method(std::string &str); std::string http_methods_to_str(unsigned int methods); void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr); +std::string str_tolower(std::string str); #endif diff --git a/srcs/webserv/cgi_script.cpp b/srcs/webserv/cgi_script.cpp index b025a28..742a6f4 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -3,7 +3,8 @@ bool Webserv::_is_cgi(Client *client) { - if (client->get_rq_path().find("/cgi-bin/") != std::string::npos) + // TMP + if (client->get_rq_abs_path().find("/cgi-bin") != std::string::npos) return true; return false; } @@ -35,7 +36,7 @@ char** Webserv::_set_env(Client *client) env[3] = _dup_env("GATEWAY_INTERFACE"); env[4] = _dup_env("PATH_INFO"); env[5] = _dup_env("PATH_TRANSLATED"); - env[6] = _dup_env("QUERY_STRING"); + env[6] = _dup_env("QUERY_STRING" , client->get_rq_query()); env[7] = _dup_env("REMOTE_ADDR" , client->get_cl_ip()); env[8] = _dup_env("REMOTE_HOST" , client->get_rq_headers("Host")); // just test env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index e5c80a3..151eb59 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -72,7 +72,7 @@ void Webserv::_construct_response(Client *client, ServerConfig &server) client->status = 413; return; } - LocationConfig &location = _determine_location(server, client->get_rq_path()); + LocationConfig &location = _determine_location(server, client->get_rq_uri()); _process_method(client, server, location); } @@ -135,7 +135,7 @@ void Webserv::_error_html_response(Client *client, ServerConfig &server) void Webserv::_get(Client *client, ServerConfig &server, LocationConfig &location) { (void)server; // To remove from arg if we determine its useless - std::string path = client->get_rq_path(); + std::string path = client->get_rq_uri(); if (path == "/") // TODO : index and autoindex path.append(INDEX); @@ -255,7 +255,7 @@ void Webserv::_post(Client *client, ServerConfig &server, LocationConfig &locati WIP https://www.rfc-editor.org/rfc/rfc9110.html#name-post */ - std::string path = client->get_rq_path(); + std::string path = client->get_rq_uri(); path.insert(0, location.root); /* CGI Here ? */ @@ -321,7 +321,7 @@ void Webserv::_delete(Client *client, ServerConfig &server, LocationConfig &loca WIP https://www.rfc-editor.org/rfc/rfc9110.html#name-delete */ - std::string path = client->get_rq_path(); + std::string path = client->get_rq_uri(); path.insert(0, location.root); /* CGI Here ? */