Merge branch 'hugo3'
+ script output verification works (field duplicate and status)
+ parsing_message_http :
- the file is deleted
- of the three functions it contained, only one still exist
- 'parse_http_headers' is now in utils
+ changes in utils :
- http headers parsing doesn't change key case itself
- a new function change key case tolower case in map<str, str>
- added split_trim() that perform a split and a trim at once
- resolved pbm in trim
- added print_special to print special char '\r' and '\n'
- del_line became extract_line, because it returns the deleted line
- added get line, that does the same without deleting
- moved http_header in utils, and made it more consistent
+ in Client :
- parse_request is now named parse_request_headers to work with parse body
- private function _parse_request_headers is then now _parse_request_fields
(because it doesn't take care of request first line, but only fields)
- added a debug function 'print_client'
This commit is contained in:
@@ -79,11 +79,8 @@ Client & Client::operator=( Client const & rhs )
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
|
||||
// https://www.ibm.com/docs/en/cics-ts/5.3?topic=protocol-http-requests
|
||||
// https://www.tutorialspoint.com/http/http_requests.htm
|
||||
void Client::parse_request(std::vector<ServerConfig> &servers)
|
||||
void Client::parse_request_headers(std::vector<ServerConfig> &servers)
|
||||
{
|
||||
std::map<std::string, std::string> headers;
|
||||
std::string body;
|
||||
|
||||
if (raw_request.find(CRLF CRLF) == NPOS)
|
||||
return ;
|
||||
header_complete = true;
|
||||
@@ -92,27 +89,37 @@ void Client::parse_request(std::vector<ServerConfig> &servers)
|
||||
_parse_request_line();
|
||||
if (status)
|
||||
return;
|
||||
_parse_request_headers();
|
||||
_parse_request_fields();
|
||||
|
||||
// DEBUG
|
||||
print_client("headers");
|
||||
|
||||
if (status)
|
||||
return;
|
||||
assigned_server = ::_determine_process_server(this, servers);
|
||||
assigned_location = ::_determine_location(*assigned_server, _request.abs_path);
|
||||
_check_request_errors();
|
||||
if (status)
|
||||
return;
|
||||
_parse_port_hostname(this->get_rq_headers("Host"));
|
||||
_parse_port_hostname(this->get_rq_headers("Host")); // use getter for headers because it works case insensitive
|
||||
|
||||
std::cerr << get_rq_method_str() << " " << get_rq_uri() << " " << get_rq_version() << "\n"; // DEBUG
|
||||
/* dont clear raw_request, we need it for future reparsing of body
|
||||
see call of parse_request() in _read_request() */
|
||||
// DEBUG
|
||||
std::cerr << get_rq_method_str() << " " << get_rq_uri() << " " << get_rq_version() << "\n";
|
||||
|
||||
// dont clear raw_request, we need it for future reparsing of body
|
||||
// see call of parse_request() in _read_request()
|
||||
// raw_request.clear();
|
||||
}
|
||||
|
||||
void Client::parse_request_body()
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
pos = raw_request.find(CRLF CRLF);
|
||||
if (pos == NPOS)
|
||||
{
|
||||
std::cerr << "parse_request_body() bad call, header incomplete\n";
|
||||
// QUESTION from hugo : don't we change the status here ?
|
||||
return;
|
||||
}
|
||||
pos += CRLF_SIZE*2;
|
||||
@@ -192,7 +199,7 @@ void Client::parse_request_body()
|
||||
///////////////
|
||||
// Body checks
|
||||
if (_request.body.size() > assigned_server->client_body_limit)
|
||||
status = 413;
|
||||
status = 413; // HTTP Client Errors
|
||||
}
|
||||
|
||||
bool Client::fill_script_path(std::string script)
|
||||
@@ -247,6 +254,33 @@ void Client::clear_script()
|
||||
_request.script.info.clear();
|
||||
}
|
||||
|
||||
// debug
|
||||
void Client::print_client(std::string message)
|
||||
{
|
||||
std::map<std::string, std::string>::iterator it;
|
||||
|
||||
std::cout << "\n=== DEBUG PRINT CLIENT ===\n";
|
||||
std::cout << message << ":\n----------\n\n" << "raw_request:\n__\n";
|
||||
::print_special(raw_request);
|
||||
std::cout << "\n__\n"
|
||||
<< "get_cl_fd() : [" << get_cl_fd() << "]\n"
|
||||
<< "get_cl_port() : [" << get_cl_port() << "]\n"
|
||||
<< "get_cl_ip() : [" << get_cl_ip() << "]\n"
|
||||
<< "get_rq_method_str() : [" << get_rq_method_str() << "]\n"
|
||||
<< "get_rq_uri() : [" << get_rq_uri() << "]\n"
|
||||
<< "get_rq_abs_path() : [" << get_rq_abs_path() << "]\n"
|
||||
<< "get_rq_query() : [" << get_rq_query() << "]\n"
|
||||
<< "get_rq_version() : [" << get_rq_version() << "]\n"
|
||||
<< "get_rq_body() : [" << get_rq_body() << "]\n"
|
||||
<< "get_rq_port() : [" << get_rq_port() << "]\n"
|
||||
<< "get_rq_hostname() : [" << get_rq_hostname() << "]\n"
|
||||
<< "get_rq_script_path() : [" << get_rq_script_path() << "]\n"
|
||||
<< "get_rq_script_info() : [" << get_rq_script_info() << "]\n"
|
||||
<< "headers :\n";
|
||||
for (it = _request.headers.begin(); it != _request.headers.end(); it++)
|
||||
std::cout << " " << it->first << ": [" << it->second << "]\n";
|
||||
std::cout << "\n=== END PRINT CLIENT ===\n\n";
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* GETTERS
|
||||
@@ -290,12 +324,13 @@ std::string Client::get_rq_headers(const std::string & key) const
|
||||
void Client::_parse_request_line()
|
||||
{
|
||||
std::vector<std::string> line;
|
||||
int ret;
|
||||
std::string raw_line;
|
||||
|
||||
ret = ::parse_http_first_line(raw_request, line);
|
||||
if (ret != 3)
|
||||
raw_line = ::get_line(raw_request, 0, CRLF);
|
||||
line = ::split_trim(raw_line, " ");
|
||||
if (line.size() != 3)
|
||||
{
|
||||
std::cerr << "err _parse_first_line(): wrong number of elements (" << ret << " instead of 3)\n";
|
||||
std::cerr << "err _parse_first_line(): wrong number of elements (" << line.size() << " instead of 3)\n";
|
||||
status = 400; // "bad request"
|
||||
}
|
||||
else
|
||||
@@ -319,10 +354,32 @@ void Client::_parse_request_uri( std::string uri )
|
||||
_request.abs_path = uri.substr(0, pos);
|
||||
}
|
||||
|
||||
void Client::_parse_request_headers()
|
||||
void Client::_parse_request_fields()
|
||||
{
|
||||
// TODO: check error and adjust status
|
||||
_request.headers = ::parse_http_headers(raw_request);
|
||||
std::string headers;
|
||||
size_t pos;
|
||||
int ret;
|
||||
|
||||
headers = raw_request;
|
||||
// delete first line
|
||||
pos = headers.find(CRLF);
|
||||
if (pos != std::string::npos)
|
||||
headers.erase(0, pos + std::string(CRLF).size());
|
||||
// delete body part
|
||||
pos = headers.find(CRLF CRLF);
|
||||
if (pos != std::string::npos)
|
||||
headers.erase(pos);
|
||||
else {
|
||||
std::cerr << "err _parse_request_fields(): request header doesn't end with empty line\n";
|
||||
status = 400; // "bad request"
|
||||
}
|
||||
// copy result of parser into headers
|
||||
ret = ::parse_http_headers(headers, _request.headers);
|
||||
if (ret > 0) {
|
||||
std::cerr << "err _parse_request_fields(): " << ret << " fields are bad formated\n";
|
||||
status = 400; // "bad request"
|
||||
}
|
||||
::str_map_key_tolower(_request.headers);
|
||||
}
|
||||
|
||||
void Client::_parse_port_hostname(std::string host)
|
||||
@@ -349,12 +406,12 @@ void Client::_check_request_errors()
|
||||
///////////////////////
|
||||
// Request line checks
|
||||
if (_request.method == UNKNOWN)
|
||||
status = 501;
|
||||
status = 501; // HTTP Client Errors
|
||||
else if (_request.version.compare(0, sizeof("HTTP/1") - 1, "HTTP/1") != 0)
|
||||
status = 505;
|
||||
status = 505; // HTTP Client Errors
|
||||
else if (!(assigned_location->allow_methods & _request.method))
|
||||
{
|
||||
status = 405;
|
||||
status = 405; // HTTP Client Errors
|
||||
response.append("Allow: ");
|
||||
response.append(::http_methods_to_str(assigned_location->allow_methods));
|
||||
response.append(CRLF);
|
||||
@@ -396,3 +453,4 @@ bool operator==(const Client& lhs, int fd)
|
||||
{ return lhs.get_cl_fd() == fd; }
|
||||
bool operator==(int fd, const Client& rhs)
|
||||
{ return fd == rhs.get_cl_fd(); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user