diff --git a/CMakeLists.txt b/CMakeLists.txt index f0c4018..b752743 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,11 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_BUILD_TYPE Debug) set(CMAKE_CXX_FLAGS "-Wall -g -fsanitize=address") -add_executable(Webserver "src/Entry.cpp" "src/Webserver.cpp" "src/HTTP.cpp" - "libs/QuickDigest5/quickdigest5.cpp" "src/Helpers.cpp") +add_executable( + Webserver + "src/Entry.cpp" "src/Webserver.cpp" "src/HTTP.cpp" + "libs/QuickDigest5/quickdigest5.cpp" "src/Helpers.cpp" + "src/HTTPRequestProcess.cpp") add_custom_command( TARGET Webserver diff --git a/README.md b/README.md index 3026dca..0d3e5f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # TNC File Hoster The Night Club's very own basic image hosting web frontend. +======= +# Web Base for C++ + +A good starting point for web development on C++. Do implement security stuff. +>>>>>>> upstream/main # Building diff --git a/src/Entry.cpp b/src/Entry.cpp index de7ae3e..622edad 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -1,4 +1,4 @@ -#include "main.hpp" +#include "Main.hpp" #include #include diff --git a/src/HTTP.cpp b/src/HTTP.cpp index d3a542f..9aadd86 100644 --- a/src/HTTP.cpp +++ b/src/HTTP.cpp @@ -1,94 +1,9 @@ #include "Helpers.hpp" -#include "main.hpp" -#include -#include -#include -#include -#include -#include -#include -#include +#include "Main.hpp" void HTTPrequest::start() { // Possible Logging here - readData(); -} - -void HTTPrequest::readData() { - // - // Reading happens here - // - std::shared_ptr self(shared_from_this()); - - // TODO: Read until headers, headers contains the file size then allocate that - // much memory on buffer, and THEN start reading the file - - // 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 bitCount = 0; - - // This is HTTP main request - std::string rq, key, value, type, path; - - Helpers::getlineAndCount(stream, bitCount, type, - ' '); // HTTP request type - Helpers::getlineAndCount(stream, bitCount, path, ' '); // HTTP path - Helpers::getlineAndCount(stream, bitCount, - rq); // Version, omitting for now - - // Quick stop to process arguments - std::stringstream pathStream(path); - std::getline(pathStream, path, '?'); // Keeping the path pure - - while (!pathStream.eof()) { - std::getline(pathStream, key, '='); - std::getline(pathStream, value, '&'); - args.insert({key, value}); - std::cout << key << " " << value << std::endl; - } - - // Rest of the request vals - while (bitCount < - packageSize - 2) { // -2 is due to last two \r\n\r\n combo - Helpers::getlineAndCount(stream, bitCount, key, ':'); - Helpers::getlineAndCount( - stream, bitCount, rq, - ' '); // trim start some gangster shit right here - Helpers::getlineAndCount(stream, bitCount, value); - request.insert({key, value}); - } - - // =================== - // BODY OF THE REQUEST - // =================== - std::size_t uploadSize = - std::stoull(request.at("Content-Length")) - buffer.size(); - asio::async_read( - sock, buffer.prepare(uploadSize), - asio::transfer_exactly(uploadSize), - [self, this](std::error_code error, std::size_t packageSize) { - buffer.commit(packageSize); - std::istream bodyStream(&buffer); - std::string body; - body.resize(buffer.size()); - bodyStream.read(body.data(), buffer.size()); - - std::cout << body << "\ntest" << std::endl; - buffer.consume(buffer.size()); - sock.close(); - }); - - processRequest(type, path, request, args); // This writes data too - sock.close(); - } - }); + processHTTPHeader(); } void HTTPrequest::processRequest( diff --git a/src/HTTPRequestProcess.cpp b/src/HTTPRequestProcess.cpp new file mode 100644 index 0000000..2f4a642 --- /dev/null +++ b/src/HTTPRequestProcess.cpp @@ -0,0 +1,89 @@ +#include "Helpers.hpp" +#include "Main.hpp" + +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; + + // This is HTTP main request + std::string rq, key, value, type, path; + + Helpers::getlineAndCount(stream, octetCount, type, + ' '); // HTTP request type + Helpers::getlineAndCount(stream, octetCount, path, ' '); // 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 + + 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 + sock.close(); + } + }); +} diff --git a/src/Helpers.cpp b/src/Helpers.cpp index 90db964..e68a012 100644 --- a/src/Helpers.cpp +++ b/src/Helpers.cpp @@ -27,7 +27,8 @@ std::string Helpers::GenerateResponse(std::string statusCode, std::string content) { std::stringstream output; output << "HTTP/1.1 " << statusCode << "\n" - << "Content-Type: " << contentType << "\nConnection: close\n\n" + << "Content-Type: " << contentType + << "\nContent-Length: " << content.size() << "\nConnection: close\n\n" << content; return output.str(); } diff --git a/src/main.hpp b/src/Main.hpp similarity index 98% rename from src/main.hpp rename to src/Main.hpp index fcfdece..bffc5c6 100644 --- a/src/main.hpp +++ b/src/Main.hpp @@ -30,7 +30,7 @@ public: private: HTTPrequest(asio::io_context &context); - void readData(); + void processHTTPHeader(); void processRequest(std::string requestType, std::string requestPath, std::unordered_map request, std::unordered_map args); diff --git a/src/Webserver.cpp b/src/Webserver.cpp index 9a49d47..906b895 100644 --- a/src/Webserver.cpp +++ b/src/Webserver.cpp @@ -1,4 +1,4 @@ -#include "main.hpp" +#include "Main.hpp" #include // Webserver is defined at main.hpp, you probably do not want to code here diff --git a/www/index.html b/www/index.html index 5a4af6f..3254160 100644 --- a/www/index.html +++ b/www/index.html @@ -8,7 +8,8 @@ -

Test

+

Welcome

+

POST test