script path is found and fill

This commit is contained in:
hugogogo
2022-08-07 15:51:36 +02:00
parent e0fd743b5b
commit 7ecfc22c7b
5 changed files with 106 additions and 46 deletions

View File

@@ -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 <name-of-cheme>":", 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 <name-of-cheme>":", 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

View File

@@ -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<std::string, std::string>::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;

View File

@@ -11,6 +11,12 @@
# include <netinet/in.h> // sockaddr_in, struct in_addr
# include <arpa/inet.h> // 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;

View File

@@ -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);

View File

@@ -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