From 7ecfc22c7b123b6b5f3627ba38d7fe0048c2af7b Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 7 Aug 2022 15:51:36 +0200 Subject: [PATCH] script path is found and fill --- README.md | 38 +++++++++++++------------ srcs/Client.cpp | 45 +++++++++++++++++++++++++---- srcs/Client.hpp | 11 +++++++ srcs/webserv/Webserv.hpp | 1 + srcs/webserv/cgi_script.cpp | 57 ++++++++++++++++++++++--------------- 5 files changed, 106 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index ac9034c..6572914 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ ## work together #### questions - in client.cpp i fill the port, is there a default one in case it's not in the request ? +- timeout server but still works ? +- path contains double "//" from `Webserv::_get()` in response.cpp +- how do we deal with cgi config default folder path or anything ? #### notifications - i changed the Client getters in two categories : @@ -13,24 +16,6 @@ - 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 @@ -110,6 +95,23 @@ ## cgi rfc [rfc 3875](https://www.rfc-editor.org/rfc/rfc3875) +#### summary : +- 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 + [3.1: server responsabilities](https://www.rfc-editor.org/rfc/rfc3875#section-3.1) - The server [...] receives the request from the client diff --git a/srcs/Client.cpp b/srcs/Client.cpp index 94dc5ae..321df1e 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -77,8 +77,11 @@ void Client::parse_request() // DEBUG std::cout << "\n" << "request:\n" << raw_request - << "START _______________________\n\n" + << "START _______________________\n\n" << raw_request + << "\nSCRIPT PATH _________________\n" + << "\npath:" << _request.script.path + << "\npath_info:" << _request.script.info << "\n END _______________________\n"; pos = (raw_request).find(CRLF CRLF); @@ -92,6 +95,24 @@ std::cout << "\n" // add "raw_request.clear()" after parsing ? for little less memory usage ? } +bool Client::fill_script_path(std::string script) +{ + size_t pos; + int len = script.size(); + std::string path = this->get_rq_abs_path(); + std::string tmp; + + pos = path.find(script); + if (pos != std::string::npos) + { + tmp = path.substr(0, pos + len); + _request.script.path = "./srcs/cgi-bin" + tmp; // TODO: deal with cgi path + _request.script.info = path.substr(pos + len); + return true; + } + return false; +} + void Client::clear() { clear_request(); @@ -103,6 +124,7 @@ void Client::clear() void Client::clear_request() { + clear_script(); _request.method = UNKNOWN; _request.uri.clear(); _request.version.clear(); @@ -114,6 +136,12 @@ void Client::clear_request() _request.hostname.clear(); } +void Client::clear_script() +{ + _request.script.path.clear(); + _request.script.info.clear(); +} + /********************************************* * GETTERS @@ -136,8 +164,17 @@ 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; } std::string Client::get_rq_headers(const std::string & key) const - { return _request.headers.find(::str_tolower(key))->second; } +{ + std::map::const_iterator it; + + it = _request.headers.find(::str_tolower(key)); + if (it == _request.headers.end()) + return ""; + return it->second; +} /********************************************* @@ -159,9 +196,7 @@ void Client::_parse_request_line( std::string rline ) tmp = ::trim(sline[0], ' '); tmp = ::trim(tmp, '\r'); _request.method = str_to_http_method(tmp); - // TODO uri in request_line - // https://www.rfc-editor.org/rfc/rfc7230#section-5.3 - // https://stackoverflow.com/questions/40311306/when-is-absoluteuri-used-from-the-http-request-specs + // uri tmp = ::trim(sline[1], ' '); tmp = ::trim(tmp, '\r'); _request.uri = tmp; diff --git a/srcs/Client.hpp b/srcs/Client.hpp index 65340a1..9d57934 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -11,6 +11,12 @@ # include // sockaddr_in, struct in_addr # include // htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa +struct Script +{ + std::string path; + std::string info; +}; + struct Request { http_method method; @@ -22,6 +28,7 @@ struct Request std::string body; std::string port; std::string hostname; + struct Script script; }; # define MAX_FILESIZE 1000000 // (1Mo) @@ -56,11 +63,15 @@ class Client 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; void parse_request(); void clear(); void clear_request(); + void clear_script(); + bool fill_script_path(std::string script); private: int _fd; diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 189bc81..85cd738 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -99,6 +99,7 @@ class Webserv void _construct_client(Client *client); char** _set_env(Client *client); char* _dup_env(std::string var, std::string val); + char* _dup_env(std::string var, int i); void _exec_script(Client *client, char **env); // epoll_update.cpp int _epoll_update(int fd, uint32_t events, int op); diff --git a/srcs/webserv/cgi_script.cpp b/srcs/webserv/cgi_script.cpp index 742a6f4..55df2d9 100644 --- a/srcs/webserv/cgi_script.cpp +++ b/srcs/webserv/cgi_script.cpp @@ -3,8 +3,10 @@ bool Webserv::_is_cgi(Client *client) { - // TMP - if (client->get_rq_abs_path().find("/cgi-bin") != std::string::npos) + // TODO see how it works with config + if (client->fill_script_path("php-cgi")) + return true; + if (client->fill_script_path("cgi_cpp.cgi")) return true; return false; } @@ -26,29 +28,39 @@ char* Webserv::_dup_env(std::string var, std::string val = "") return ( strdup(str.c_str()) ); } +char* Webserv::_dup_env(std::string var, int i) +{ + std::string str; + std::string val; + + val = ::itos(i); + str = var + "=" + val; + return ( strdup(str.c_str()) ); +} + char** Webserv::_set_env(Client *client) { char** env = new char*[19]; - env[0] = _dup_env("AUTH_TYPE"); - env[1] = _dup_env("CONTENT_LENGTH" , "665"); - env[2] = _dup_env("CONTENT_TYPE"); - env[3] = _dup_env("GATEWAY_INTERFACE"); - env[4] = _dup_env("PATH_INFO"); - env[5] = _dup_env("PATH_TRANSLATED"); - 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 - env[10] = _dup_env("REMOTE_USER"); // authentification not supported - env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str()); - env[12] = _dup_env("SCRIPT_NAME"); // TODO: define (https://www.rfc-editor.org/rfc/rfc3875#section-4.1.13 - // ,https://www.rfc-editor.org/rfc/rfc3875#section-8.2) - env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname()); - env[14] = _dup_env("SERVER_PORT" , client->get_rq_port()); - env[15] = _dup_env("SERVER_PROTOCOL", client->get_rq_version()); - env[16] = _dup_env("SERVER_SOFTWARE", "webser/1.0"); - env[17] = _dup_env("REDIRECT_STATUS", "200"); + env[0] = _dup_env("AUTH_TYPE"); // authentification not supported + env[1] = _dup_env("CONTENT_LENGTH" , client->get_rq_body().size()); + env[2] = _dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type")); + env[3] = _dup_env("GATEWAY_INTERFACE" , "CGI/1.0"); + env[4] = _dup_env("PATH_INFO" , client->get_rq_script_info()); + env[5] = _dup_env("PATH_TRANSLATED"); // not supported + 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 + env[10] = _dup_env("REMOTE_USER"); // authentification not supported + env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str()); + env[12] = _dup_env("SCRIPT_NAME"); // TODO: define (https://www.rfc-editor.org/rfc/rfc3875#section-4.1.13 + // ,https://www.rfc-editor.org/rfc/rfc3875#section-8.2) + env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname()); + env[14] = _dup_env("SERVER_PORT" , client->get_rq_port()); + env[15] = _dup_env("SERVER_PROTOCOL" , client->get_rq_version()); + env[16] = _dup_env("SERVER_SOFTWARE" , "webser/1.0"); + env[17] = _dup_env("REDIRECT_STATUS" , "200"); env[18] = NULL; return env; @@ -65,8 +77,7 @@ void Webserv::_exec_script(Client *client, char **env) if (fork() == 0) { dup2(client->get_cl_fd(), STDOUT_FILENO); -// execve("./srcs/cgi-bin/cgi_cpp.cgi", nll, client->env); - execve("./srcs/cgi-bin/php-cgi", nll, env); + execve(client->get_rq_script_path().c_str(), nll, env); } // inside parent process else