key fields headers in map are in lowercase
+ getters for this map are case insensitive + change request fiel 'path' for 'uri', 'query', and 'abs_path'
This commit is contained in:
46
README.md
46
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 ?
|
- 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
|
#### notifications
|
||||||
- ce header est soit "Content-Type", soit "Location", soit "Status"
|
- i changed the Client getters in two categories :
|
||||||
- il peut dans certains cas envoyer d'autres headers
|
- getters for requests infos : `get_rq_<info>`
|
||||||
- le serveur doit verifier qu'il n'y a pas de doublons dans les headers
|
- getters for client sides infos : `get_cl_<info>` (such as ip of client)
|
||||||
- le serveur doit verifier le formatage des headers (typiquement l'encodage, par exemple pour les newlines)
|
- i changed the variables in request struct in Client :
|
||||||
- ? comment on passe le body-message au script ? section 4.2
|
- `path` become `uri` (ex. /path/to/file?var=val)
|
||||||
-> en ecrivant le body dans le fd temp sur lequel on a branché stdin et stdout avant d'execve le script
|
- add `abs_path` (ex. /path/to/file )
|
||||||
- ? on doit gerer l'authentification ?
|
- add `query` (ex. var=val)
|
||||||
-> pas pour l'instant on va dire :p
|
- the header fields names, as key in map, are stored in lowercase, and getters are case-insensitives
|
||||||
- ? pourquoi on construit un script-cgi ? section 3.3
|
|
||||||
- ? on doit gerer l'authentification ?
|
#### share knowledge
|
||||||
- ? pourquoi on doit construire un script-cgi ? section 3.3
|
##### cgi
|
||||||
- ? si l'uri correspond au script-cgi, ca appel le script donc ? section 3.3
|
- 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
|
## man
|
||||||
@@ -141,10 +157,12 @@
|
|||||||
- local redirect response :
|
- local redirect response :
|
||||||
- it must return only a Location field
|
- it must return only a Location field
|
||||||
- it contains a local path URI and query string ('local-pathquery')
|
- 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
|
- the server must generate the response for this local-pathquery
|
||||||
- client redirect response :
|
- client redirect response :
|
||||||
- it must return only a Location field
|
- 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
|
- 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
|
- the http server must generate a 302 'Found' message
|
||||||
- client redirect response with document
|
- client redirect response with document
|
||||||
- it must return a Location field with an absolute URI path
|
- it must return a Location field with an absolute URI path
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ void Client::parse_request()
|
|||||||
std::vector<std::string> list;
|
std::vector<std::string> list;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
std::cout << "\n"
|
std::cout << "\n"
|
||||||
<< "request:\n" << raw_request
|
<< "request:\n" << raw_request
|
||||||
<< "START _______________________\n\n"
|
<< "START _______________________\n\n"
|
||||||
@@ -87,7 +88,7 @@ std::cout << "\n"
|
|||||||
list.erase(list.begin());
|
list.erase(list.begin());
|
||||||
_parse_request_headers(list);
|
_parse_request_headers(list);
|
||||||
_parse_request_body(pos + 4);
|
_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 ?
|
// add "raw_request.clear()" after parsing ? for little less memory usage ?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +104,14 @@ void Client::clear()
|
|||||||
void Client::clear_request()
|
void Client::clear_request()
|
||||||
{
|
{
|
||||||
_request.method = UNKNOWN;
|
_request.method = UNKNOWN;
|
||||||
_request.path.clear();
|
_request.uri.clear();
|
||||||
_request.version.clear();
|
_request.version.clear();
|
||||||
_request.headers.clear();
|
_request.headers.clear();
|
||||||
_request.body.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
|
// 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; }
|
std::string Client::get_cl_ip() const { return _ip; }
|
||||||
listen_socket * Client::get_cl_lsocket() const { return _lsocket; }
|
listen_socket * Client::get_cl_lsocket() const { return _lsocket; }
|
||||||
std::string Client::get_cl_port() const { return _port; }
|
std::string Client::get_cl_port() const { return _port; }
|
||||||
|
|
||||||
// requette
|
// 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 Client::get_rq_method_str() const
|
||||||
{
|
{ return ::http_methods_to_str(_request.method); }
|
||||||
std::string method;
|
std::string Client::get_rq_uri() const { return _request.uri; }
|
||||||
method = ::http_methods_to_str(_request.method);
|
std::string Client::get_rq_abs_path() const { return _request.abs_path; }
|
||||||
return method;
|
std::string Client::get_rq_query() const { return _request.query; }
|
||||||
}
|
|
||||||
std::string Client::get_rq_path() const { return _request.path; }
|
|
||||||
std::string Client::get_rq_version() const { return _request.version; }
|
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_body() const { return _request.body; }
|
||||||
std::string Client::get_rq_port() const { return _request.port; }
|
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_hostname() const { return _request.hostname; }
|
||||||
std::string Client::get_rq_headers(const std::string & key)
|
std::string Client::get_rq_headers(const std::string & key) const
|
||||||
{ return _request.headers[key]; }
|
{ 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
|
// https://stackoverflow.com/questions/40311306/when-is-absoluteuri-used-from-the-http-request-specs
|
||||||
tmp = ::trim(sline[1], ' ');
|
tmp = ::trim(sline[1], ' ');
|
||||||
tmp = ::trim(tmp, '\r');
|
tmp = ::trim(tmp, '\r');
|
||||||
_request.path = tmp;
|
_request.uri = tmp;
|
||||||
|
_parse_request_uri( tmp );
|
||||||
// http version
|
// http version
|
||||||
tmp = ::trim(sline[2], ' ');
|
tmp = ::trim(sline[2], ' ');
|
||||||
tmp = ::trim(tmp, '\r');
|
tmp = ::trim(tmp, '\r');
|
||||||
_request.version = tmp;
|
_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<std::string> list )
|
void Client::_parse_request_headers( std::vector<std::string> list )
|
||||||
{
|
{
|
||||||
std::string key;
|
std::string key;
|
||||||
@@ -180,6 +197,7 @@ void Client::_parse_request_headers( std::vector<std::string> list )
|
|||||||
key = (*it).substr( 0, pos );
|
key = (*it).substr( 0, pos );
|
||||||
key = ::trim(key, ' ');
|
key = ::trim(key, ' ');
|
||||||
key = ::trim(key, '\r');
|
key = ::trim(key, '\r');
|
||||||
|
key = ::str_tolower(key);
|
||||||
val = (*it).substr( pos + 1 );
|
val = (*it).substr( pos + 1 );
|
||||||
val = ::trim(val, ' ');
|
val = ::trim(val, ' ');
|
||||||
val = ::trim(val, '\r');
|
val = ::trim(val, '\r');
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
struct Request
|
struct Request
|
||||||
{
|
{
|
||||||
http_method method;
|
http_method method;
|
||||||
std::string path;
|
std::string uri;
|
||||||
|
std::string abs_path;
|
||||||
|
std::string query;
|
||||||
std::string version;
|
std::string version;
|
||||||
std::map<std::string, std::string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
std::string body;
|
std::string body;
|
||||||
@@ -38,10 +40,6 @@ class Client
|
|||||||
size_t body_size;
|
size_t body_size;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
// std::string port;
|
|
||||||
// std::string ip;
|
|
||||||
// listen_socket * lsocket;
|
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
int get_cl_fd() const;
|
int get_cl_fd() const;
|
||||||
std::string get_cl_port() const;
|
std::string get_cl_port() const;
|
||||||
@@ -51,12 +49,14 @@ class Client
|
|||||||
// requests getters
|
// requests getters
|
||||||
http_method get_rq_method() const;
|
http_method get_rq_method() const;
|
||||||
std::string get_rq_method_str() 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_version() const;
|
||||||
std::string get_rq_body() const;
|
std::string get_rq_body() const;
|
||||||
std::string get_rq_port() const;
|
std::string get_rq_port() const;
|
||||||
std::string get_rq_hostname() 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 parse_request();
|
||||||
void clear();
|
void clear();
|
||||||
@@ -70,6 +70,7 @@ class Client
|
|||||||
struct Request _request;
|
struct Request _request;
|
||||||
|
|
||||||
void _parse_request_line( std::string rline );
|
void _parse_request_line( std::string rline );
|
||||||
|
void _parse_request_uri( std::string uri );
|
||||||
void _parse_request_headers( std::vector<std::string> list );
|
void _parse_request_headers( std::vector<std::string> list );
|
||||||
void _parse_request_body( size_t pos );
|
void _parse_request_body( size_t pos );
|
||||||
void _parse_port_hostname(std::string host);
|
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);
|
bool operator==(int fd, const Client& rhs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -105,3 +105,10 @@ bool operator==(const listen_socket& lhs, int fd)
|
|||||||
|
|
||||||
bool operator==(int fd, const listen_socket& rhs)
|
bool operator==(int fd, const listen_socket& rhs)
|
||||||
{ return fd == rhs.fd; }
|
{ return fd == rhs.fd; }
|
||||||
|
|
||||||
|
std::string str_tolower(std::string str)
|
||||||
|
{
|
||||||
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
# include <string>
|
# include <string>
|
||||||
# include <sstream>
|
# include <sstream>
|
||||||
# include <cstdlib> // atoi
|
# include <cstdlib> // atoi
|
||||||
|
# include <cctype> // tolower
|
||||||
|
# include <algorithm> // transform
|
||||||
|
|
||||||
# define CR "\r"
|
# define CR "\r"
|
||||||
# define LF "\n"
|
# define LF "\n"
|
||||||
@@ -46,5 +48,6 @@ std::string trim(std::string str, char c);
|
|||||||
http_method str_to_http_method(std::string &str);
|
http_method str_to_http_method(std::string &str);
|
||||||
std::string http_methods_to_str(unsigned int methods);
|
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);
|
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
|
#endif
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
bool Webserv::_is_cgi(Client *client)
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,7 @@ char** Webserv::_set_env(Client *client)
|
|||||||
env[3] = _dup_env("GATEWAY_INTERFACE");
|
env[3] = _dup_env("GATEWAY_INTERFACE");
|
||||||
env[4] = _dup_env("PATH_INFO");
|
env[4] = _dup_env("PATH_INFO");
|
||||||
env[5] = _dup_env("PATH_TRANSLATED");
|
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[7] = _dup_env("REMOTE_ADDR" , client->get_cl_ip());
|
||||||
env[8] = _dup_env("REMOTE_HOST" , client->get_rq_headers("Host")); // just test
|
env[8] = _dup_env("REMOTE_HOST" , client->get_rq_headers("Host")); // just test
|
||||||
env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported
|
env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ void Webserv::_construct_response(Client *client, ServerConfig &server)
|
|||||||
client->status = 413;
|
client->status = 413;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LocationConfig &location = _determine_location(server, client->get_rq_path());
|
LocationConfig &location = _determine_location(server, client->get_rq_uri());
|
||||||
_process_method(client, server, location);
|
_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 Webserv::_get(Client *client, ServerConfig &server, LocationConfig &location)
|
||||||
{
|
{
|
||||||
(void)server; // To remove from arg if we determine its useless
|
(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
|
if (path == "/") // TODO : index and autoindex
|
||||||
path.append(INDEX);
|
path.append(INDEX);
|
||||||
@@ -255,7 +255,7 @@ void Webserv::_post(Client *client, ServerConfig &server, LocationConfig &locati
|
|||||||
WIP
|
WIP
|
||||||
https://www.rfc-editor.org/rfc/rfc9110.html#name-post
|
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);
|
path.insert(0, location.root);
|
||||||
|
|
||||||
/* CGI Here ? */
|
/* CGI Here ? */
|
||||||
@@ -321,7 +321,7 @@ void Webserv::_delete(Client *client, ServerConfig &server, LocationConfig &loca
|
|||||||
WIP
|
WIP
|
||||||
https://www.rfc-editor.org/rfc/rfc9110.html#name-delete
|
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);
|
path.insert(0, location.root);
|
||||||
|
|
||||||
/* CGI Here ? */
|
/* CGI Here ? */
|
||||||
|
|||||||
Reference in New Issue
Block a user