#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 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 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 list ) { std::string key; std::string val; std::vector::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(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(); }