279 lines
6.5 KiB
C++
279 lines
6.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._fd )
|
|
, _port ( src._port )
|
|
, _ip ( src._ip )
|
|
, _lsocket ( src._lsocket )
|
|
{
|
|
raw_request = src.raw_request;
|
|
response = src.response;
|
|
// buf = strdup(src.buf); // TODO: this doesn't work
|
|
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;
|
|
|
|
// DEBUG
|
|
std::cout << "\nREQUEST _____________________\n"
|
|
<< raw_request
|
|
<< "\n\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(this->get_rq_headers("Host"));
|
|
raw_request.clear();
|
|
}
|
|
|
|
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 == 0)
|
|
{
|
|
tmp = path.substr(0, pos + len);
|
|
_request.script.path = "./srcs" + tmp; // TODO: root path ?
|
|
_request.script.info = path.substr(pos + len);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Client::clear()
|
|
{
|
|
clear_request();
|
|
raw_request.clear();
|
|
response.clear();
|
|
body_size = 0;
|
|
status = 0;
|
|
}
|
|
|
|
void Client::clear_request()
|
|
{
|
|
clear_script();
|
|
_request.method = UNKNOWN;
|
|
_request.uri.clear();
|
|
_request.version.clear();
|
|
_request.headers.clear();
|
|
_request.body.clear();
|
|
_request.abs_path.clear();
|
|
_request.query.clear();
|
|
_request.port.clear();
|
|
_request.hostname.clear();
|
|
}
|
|
|
|
void Client::clear_script()
|
|
{
|
|
_request.script.path.clear();
|
|
_request.script.info.clear();
|
|
}
|
|
|
|
|
|
/*********************************************
|
|
* GETTERS
|
|
*********************************************/
|
|
|
|
// client side
|
|
int Client::get_cl_fd() const { return _fd; }
|
|
const std::string & Client::get_cl_ip() const { return _ip; }
|
|
const std::string & Client::get_cl_port() const { return _port; }
|
|
const listen_socket * Client::get_cl_lsocket() const { return _lsocket; }
|
|
|
|
// requette
|
|
http_method Client::get_rq_method() const { return _request.method; }
|
|
std::string Client::get_rq_method_str() const
|
|
{ return ::http_methods_to_str(_request.method); }
|
|
std::string Client::get_rq_uri() const { return _request.uri; }
|
|
std::string Client::get_rq_abs_path() const { return _request.abs_path; }
|
|
std::string Client::get_rq_query() const { return _request.query; }
|
|
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
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
/*********************************************
|
|
* 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);
|
|
// uri
|
|
tmp = ::trim(sline[1], ' ');
|
|
tmp = ::trim(tmp, '\r');
|
|
_request.uri = tmp;
|
|
_parse_request_uri( tmp );
|
|
// http version
|
|
tmp = ::trim(sline[2], ' ');
|
|
tmp = ::trim(tmp, '\r');
|
|
_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 )
|
|
{
|
|
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');
|
|
key = ::str_tolower(key);
|
|
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(); }
|
|
|