Files
42_INT_12_webserv/srcs/Client.cpp
2022-08-06 19:58:09 +02:00

231 lines
5.5 KiB
C++

#include "Client.hpp"
char Client::buf[MAX_FILESIZE+1];
/*********************************************
* COPLIENS
*********************************************/
Client::Client()
: body_size(0)
, status(0)
, _fd(0)
{
return;
}
//Client::Client(int afd, listen_socket *lsocket, struct sockaddr_in addr)
Client::Client(int afd, listen_socket *lsocket, std::string aport, std::string aip)
: body_size(0)
, status(0)
, _fd(afd)
, _port(aport)
, _ip(aip)
, _lsocket(lsocket)
{
return;
}
Client::~Client() {
return;
}
// WIP placeholder because of const values
Client::Client( Client const & src )
: body_size(0)
, status(0)
, _fd ( src.get_cl_fd() )
, _port ( src.get_cl_port() )
, _ip ( src.get_cl_ip() )
, _lsocket ( src.get_cl_lsocket() )
{
raw_request = src.raw_request;
response = src.response;
// buf = strdup(src.buf);
body_size = src.body_size;
status = src.status;
return;
}
// WIP placeholder because of const values
Client & Client::operator=( Client const & rhs )
{
if ( this != &rhs )
{
// stuff
}
return *this;
}
/*********************************************
* PUBLIC MEMBER FUNCTIONS
*********************************************/
// http headers :
// 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::string sub;
std::vector<std::string> list;
size_t pos;
std::cout << "\n"
<< "request:\n" << raw_request
<< "START _______________________\n\n"
<< raw_request
<< "\n END _______________________\n";
pos = (raw_request).find(CRLF CRLF);
sub = (raw_request).substr(0, pos);
list = split(sub, '\n');
_parse_request_line(*list.begin());
list.erase(list.begin());
_parse_request_headers(list);
_parse_request_body(pos + 4);
_parse_port_hostname(_request.headers["Host"]);
// add "raw_request.clear()" after parsing ? for little less memory usage ?
}
void Client::clear()
{
clear_request();
raw_request.clear();
response.clear();
body_size = 0;
status = 0;
}
void Client::clear_request()
{
_request.method = UNKNOWN;
_request.path.clear();
_request.version.clear();
_request.headers.clear();
_request.body.clear();
}
/*********************************************
* GETTERS
*********************************************/
// client side
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; }
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; }
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]; }
/*********************************************
* PRIVATE MEMBER FUNCTIONS
*********************************************/
void Client::_parse_request_line( std::string rline )
{
std::vector<std::string> sline;
std::string tmp;
sline = split(rline, ' ');
if (sline.size() != 3)
{
std::cerr << "err _parse_request_line(): ";
throw std::runtime_error("bad request-line header");
}
// method
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
tmp = ::trim(sline[1], ' ');
tmp = ::trim(tmp, '\r');
_request.path = tmp;
// http version
tmp = ::trim(sline[2], ' ');
tmp = ::trim(tmp, '\r');
_request.version = tmp;
}
void Client::_parse_request_headers( std::vector<std::string> list )
{
std::string key;
std::string val;
std::vector<std::string>::iterator it;
size_t pos;
for (it = list.begin(); it != list.end(); it++)
{
pos = (*it).find(':');
key = (*it).substr( 0, pos );
key = ::trim(key, ' ');
key = ::trim(key, '\r');
val = (*it).substr( pos + 1 );
val = ::trim(val, ' ');
val = ::trim(val, '\r');
_request.headers.insert( std::pair<std::string, std::string>(key, val) );
}
}
void Client::_parse_request_body( size_t pos )
{
std::string body = &raw_request[pos];
_request.body = body;
}
void Client::_parse_port_hostname(std::string host)
{
size_t pos;
if (host == "")
{
std::cerr << "no host\n";
throw std::runtime_error("no host in request");
}
pos = host.find(':');
// port :
if (pos == std::string::npos)
_request.port = "4040"; // TODO: make equal to default port in config
else
_request.port = host.substr(pos);
if (_request.port == ":")
_request.port = "";
// hostname :
_request.hostname = host.substr(0, pos);
}
/*********************************************
* OVERLOAD
*********************************************/
bool operator==(const Client& lhs, const Client& rhs)
{ return lhs.get_cl_fd() == rhs.get_cl_fd(); }
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(); }