diff --git a/src/HTTP.cpp b/src/HTTP.cpp index 9aadd86..06d250c 100644 --- a/src/HTTP.cpp +++ b/src/HTTP.cpp @@ -6,10 +6,7 @@ void HTTPrequest::start() { processHTTPHeader(); } -void HTTPrequest::processRequest( - std::string requestType, std::string requestPath, - std::unordered_map request, - std::unordered_map args) { +void HTTPrequest::processRequest() { // // This is where we will process requests // diff --git a/src/HTTPRequestProcess.cpp b/src/HTTPRequestProcess.cpp index 2f4a642..648fed1 100644 --- a/src/HTTPRequestProcess.cpp +++ b/src/HTTPRequestProcess.cpp @@ -1,89 +1,94 @@ #include "Helpers.hpp" #include "Main.hpp" +#include + +// TODO: Remove boundary from the body. Do keep other stuff like +// file type and name void HTTPrequest::processHTTPHeader() { - // - // Reading happens here - // std::shared_ptr self(shared_from_this()); - // Sadly due to the nature of how asio works this entire logic needs to be - // mostly in 1 method I do wager that I could break off the whole body - // processing into its own thing as well as a lot of inline methods - // specifically for argument and header processing - - // TODO: Remove boundary from the body. Do keep other stuff like - // file type and name - // HEADER read asio::async_read_until( sock, buffer, "\r\n\r\n", // its not the other way bud [this, self](std::error_code error, std::size_t packageSize) { if (!error) { buffer.commit(packageSize); - std::unordered_map request; - std::unordered_map args; std::istream stream(&buffer); - uint64_t octetCount = 0; + std::size_t octetCount = 0; // This is HTTP main request - std::string rq, key, value, type, path; - - Helpers::getlineAndCount(stream, octetCount, type, + std::string rq; + Helpers::getlineAndCount(stream, octetCount, requestType, ' '); // HTTP request type - Helpers::getlineAndCount(stream, octetCount, path, ' '); // HTTP path + Helpers::getlineAndCount(stream, octetCount, requestPath, + ' '); // HTTP path Helpers::getlineAndCount(stream, octetCount, rq); // Version, omitting for now - // Quick stop to process arguments - if (path.find('?') != std::string::npos) { - std::stringstream pathStream(path); - std::getline(pathStream, path, '?'); // Keeping the path pure + // Get arguments and other header stuff out of the way + processArgs(); + processHeaderValues(stream, octetCount, packageSize); + processBody(); - while (!pathStream.eof()) { - std::getline(pathStream, key, '='); - std::getline(pathStream, value, '&'); - args.insert({key, value}); - } - } - - // Rest of the request vals - while (octetCount < - packageSize - 2) { // -2 is due to last two \r\n\r\n combo - Helpers::getlineAndCount(stream, octetCount, key, ':'); - Helpers::getlineAndCount( - stream, octetCount, rq, - ' '); // trim start some gangster shit right here - Helpers::getlineAndCount(stream, octetCount, value); - request.insert({key, value}); - } - - // =================== - // BODY OF THE REQUEST - // =================== - if (request.find("Content-Length") != request.end()) { - std::size_t uploadSize = std::stoull(request.at("Content-Length")) - - buffer.size(), - octetCount = 0; - - // This part needs to be sync since we want this specific instance - // execution to pause - while (octetCount < uploadSize) { - octetCount += asio::read(sock, buffer.prepare(uploadSize)); - } - - buffer.commit(octetCount); - std::istream bodyStream(&buffer); - std::string body; - body.resize(buffer.size()); - bodyStream.read(body.data(), buffer.size()); - - buffer.consume( - buffer.size()); // Just so the buffer is nice and clean - } - - processRequest(type, path, request, args); // This writes data too + processRequest(); // This writes data too sock.close(); } }); } + +// =================== +// Inline Helpers +// =================== + +void inline HTTPrequest::processArgs() { + std::string key, value; + if (requestPath.find('?') != std::string::npos) { + std::stringstream pathStream(requestPath); + std::getline(pathStream, requestPath, '?'); // Keeping the path pure + + while (!pathStream.eof()) { + std::getline(pathStream, key, '='); + std::getline(pathStream, value, '&'); + args.insert({key, value}); + } + } +} + +void inline HTTPrequest::processHeaderValues(std::basic_istream &stream, + std::size_t &octetCount, + std::size_t headerSize) { + std::string key, value, empty; + while (octetCount < headerSize - 2) { // -2 is due to last two \r\n\r\n combo + Helpers::getlineAndCount(stream, octetCount, key, ':'); + Helpers::getlineAndCount(stream, octetCount, empty, + ' '); // trim start some gangster shit right here + Helpers::getlineAndCount(stream, octetCount, value); + headers.insert({key, value}); + } +} + +// =================== +// BODY OF THE REQUEST +// =================== + +void inline HTTPrequest::processBody() { + if (headers.find("Content-Length") != headers.end()) { + std::size_t uploadSize = + std::stoull(headers.at("Content-Length")) - buffer.size(), + octetCount = 0; + + // This part needs to be sync since we want this specific instance + // execution to pause + while (octetCount < uploadSize) { + octetCount += asio::read(sock, buffer.prepare(uploadSize)); + } + + buffer.commit(octetCount); + std::istream bodyStream(&buffer); + bodyContent.resize(buffer.size()); + bodyStream.read(bodyContent.data(), buffer.size()); + + buffer.consume(buffer.size()); // Just so the buffer is nice and clean + } +} diff --git a/src/Main.hpp b/src/Main.hpp index bffc5c6..ec30f0f 100644 --- a/src/Main.hpp +++ b/src/Main.hpp @@ -18,7 +18,7 @@ using asocket = asio::ip::tcp::socket; using asocket_ptr = std::shared_ptr; -// We handle HTTP requests with readData, writeData, and processRequest +// We handle HTTP requests with processHTTPHeader, writeData, and processRequest class HTTPrequest : public std::enable_shared_from_this { public: typedef std::shared_ptr HTTPrequest_ptr; @@ -30,12 +30,23 @@ public: private: HTTPrequest(asio::io_context &context); - void processHTTPHeader(); - void processRequest(std::string requestType, std::string requestPath, - std::unordered_map request, - std::unordered_map args); + void processRequest(); void writeData(std::string data); + // Breaking Header to in lines + void processHTTPHeader(); + void inline processArgs(); + void inline processHeaderValues(std::basic_istream &stream, + std::size_t &octetCount, + std::size_t headerSize); + void inline processBody(); + + // Request itself + std::string requestType, requestPath; + std::unordered_map headers, args; + std::string bodyContent; + + // Networking asio::ip::tcp::socket sock; asio::streambuf buffer; };