From a4d9e3ebb567ad709d6f620baee973a6120addac Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 15 Jun 2025 16:32:29 +1200 Subject: [PATCH] 'Generic Commit' --- src/HttpController.cpp | 10 ---------- src/HttpController.hpp | 5 ----- src/put_handler.cpp | 33 ++++++++++++++++++++++++++------- src/server.cpp | 13 +++++++++++-- src/server.hpp | 12 ++++++++++-- testing/test.sh | 9 +++++++++ 6 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/HttpController.cpp b/src/HttpController.cpp index f983266..8332370 100644 --- a/src/HttpController.cpp +++ b/src/HttpController.cpp @@ -158,15 +158,5 @@ void HttpController::getAny(const drogon::HttpRequestPtr &req, } } -void HttpController::putNotFound(const drogon::HttpRequestPtr &req, - std::function &&callback, - const std::string &path) { - auto resp = drogon::HttpResponse::newHttpResponse(); - resp->setStatusCode(drogon::k404NotFound); - nlohmann::json response = {{"result", "error"}, {"error", "Not found - put requests must be to /upload"}}; - resp->setBody(response.dump()); - resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - callback(resp); -} } // namespace simple_object_storage \ No newline at end of file diff --git a/src/HttpController.hpp b/src/HttpController.hpp index 1a1b985..ea1cb0e 100644 --- a/src/HttpController.hpp +++ b/src/HttpController.hpp @@ -21,7 +21,6 @@ public: ADD_METHOD_TO(HttpController::getObject, "/object/{1}", {drogon::Get}); ADD_METHOD_TO(HttpController::getRoot, "/", {drogon::Get}); ADD_METHOD_TO(HttpController::getAny, "/{1}", {drogon::Get}); - ADD_METHOD_TO(HttpController::putNotFound, "/{1}", {drogon::Put}); METHOD_LIST_END void getIndex(const drogon::HttpRequestPtr &req, @@ -68,10 +67,6 @@ public: void getAny(const drogon::HttpRequestPtr &req, std::function &&callback, const std::string &path); - - void putNotFound(const drogon::HttpRequestPtr &req, - std::function &&callback, - const std::string &path); }; } // namespace simple_object_storage \ No newline at end of file diff --git a/src/put_handler.cpp b/src/put_handler.cpp index 6b87e23..0604930 100644 --- a/src/put_handler.cpp +++ b/src/put_handler.cpp @@ -46,6 +46,25 @@ void PutHandler::handle_put_object(const drogon::HttpRequestPtr& req, std::funct return; } + // Check content length first + auto contentLengthHeader = req->getHeader("content-length"); + if (!contentLengthHeader.empty()) { + try { + size_t contentLength = std::stoull(contentLengthHeader); + const size_t MAX_UPLOAD_SIZE = 2ULL * 1024 * 1024 * 1024; // 2GB + if (contentLength > MAX_UPLOAD_SIZE) { + resp->setStatusCode(drogon::k413RequestEntityTooLarge); + nlohmann::json response = {{"result", "error"}, {"error", "File too large"}}; + resp->setBody(response.dump()); + resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); + callback(resp); + return; + } + } catch (const std::exception&) { + // Invalid content-length header, continue with parsing + } + } + // Parse the multipart form data drogon::MultiPartParser fileParser; if (fileParser.parse(req) != 0) { @@ -169,20 +188,20 @@ void PutHandler::handle_put_object(const drogon::HttpRequestPtr& req, std::funct return; } - // Write file content to temporary file - auto fileContent = fileData->fileContent(); - if (!temp_file.write(fileContent.data(), fileContent.size())) { + temp_file.close(); + + // Use Drogon's built-in file saving for large files + try { + fileData->saveAs(temp_path.string()); + } catch (const std::exception& e) { resp->setStatusCode(drogon::k500InternalServerError); - nlohmann::json response = {{"result", "error"}, {"error", "Failed to write to temporary file"}}; + nlohmann::json response = {{"result", "error"}, {"error", "Failed to write to temporary file: " + std::string(e.what())}}; resp->setBody(response.dump()); resp->setContentTypeCode(drogon::CT_APPLICATION_JSON); - temp_file.close(); std::filesystem::remove(temp_path); callback(resp); return; } - - temp_file.close(); // Ensure the temporary file is removed even if errors occur ScopeFileDeleter temp_file_deleter(temp_path); diff --git a/src/server.cpp b/src/server.cpp index 5c64906..cc10561 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -23,6 +23,7 @@ namespace simple_object_storage { Server* Server::instance_ = nullptr; +std::mutex Server::instance_mutex_; bool Server::init_db() { @@ -145,6 +146,11 @@ bool Server::start() { drogon::app().addListener(config_.host, config_.port); drogon::app().setThreadNum(16); + // Set security limits (allowing for 1GB+ files for testing) + drogon::app().setClientMaxBodySize(2ULL * 1024 * 1024 * 1024); // 2GB max body size + drogon::app().setClientMaxMemoryBodySize(100 * 1024 * 1024); // 100MB max memory body (keep this lower) + drogon::app().enableGzip(true); // Enable compression + // Start the server try { drogon::app().run(); @@ -165,9 +171,11 @@ void Server::stop() { } void Server::setup_routes() { - // Configure global filters for CORS + // Configure CORS only for requests with Origin header drogon::app().registerPostHandlingAdvice([this](const drogon::HttpRequestPtr &req, const drogon::HttpResponsePtr &resp) { - add_cors_headers(req, resp); + if (!req->getHeader("Origin").empty()) { + add_cors_headers(req, resp); + } }); // Handle OPTIONS requests for CORS preflight @@ -175,6 +183,7 @@ void Server::setup_routes() { std::function &&callback) { handle_cors_preflight(req, std::move(callback)); }, {}, "OPTIONS"); + } void Server::handle_cors_preflight(const drogon::HttpRequestPtr& req, std::function&& callback) { diff --git a/src/server.hpp b/src/server.hpp index 548e3cb..7cc1bf8 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -20,8 +21,14 @@ public: Server(const ServerConfig& config); ~Server(); - static Server* getInstance() { return instance_; } - static void setInstance(Server* server) { instance_ = server; } + static Server* getInstance() { + std::lock_guard lock(instance_mutex_); + return instance_; + } + static void setInstance(Server* server) { + std::lock_guard lock(instance_mutex_); + instance_ = server; + } bool start(); void stop(); @@ -54,6 +61,7 @@ private: std::unique_ptr auth_rate_limiter_; static Server* instance_; + static std::mutex instance_mutex_; }; } // namespace simple_object_storage \ No newline at end of file diff --git a/testing/test.sh b/testing/test.sh index ce433b8..2cbd04a 100755 --- a/testing/test.sh +++ b/testing/test.sh @@ -414,5 +414,14 @@ if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject? die "failed to delete ${TODELHASH}" fi +#------------------------------------------------------------------------------------------------ + +function test_1GB_file_upload() { + source test_1GB_file_upload.sh +} + +title "Testing 1GB File upload" +test_1GB_file_upload + #------------------------------------------------------------------------------------------------ title "ALL TESTS PASSED"