'Generic Commit'
This commit is contained in:
@@ -158,15 +158,5 @@ void HttpController::getAny(const drogon::HttpRequestPtr &req,
|
||||
}
|
||||
}
|
||||
|
||||
void HttpController::putNotFound(const drogon::HttpRequestPtr &req,
|
||||
std::function<void(const drogon::HttpResponsePtr &)> &&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
|
@@ -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<void(const drogon::HttpResponsePtr &)> &&callback,
|
||||
const std::string &path);
|
||||
|
||||
void putNotFound(const drogon::HttpRequestPtr &req,
|
||||
std::function<void(const drogon::HttpResponsePtr &)> &&callback,
|
||||
const std::string &path);
|
||||
};
|
||||
|
||||
} // namespace simple_object_storage
|
@@ -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);
|
||||
|
@@ -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<void(const drogon::HttpResponsePtr &)> &&callback) {
|
||||
handle_cors_preflight(req, std::move(callback));
|
||||
}, {}, "OPTIONS");
|
||||
|
||||
}
|
||||
|
||||
void Server::handle_cors_preflight(const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr &)>&& callback) {
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <drogon/drogon.h>
|
||||
@@ -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<std::mutex> lock(instance_mutex_);
|
||||
return instance_;
|
||||
}
|
||||
static void setInstance(Server* server) {
|
||||
std::lock_guard<std::mutex> lock(instance_mutex_);
|
||||
instance_ = server;
|
||||
}
|
||||
|
||||
bool start();
|
||||
void stop();
|
||||
@@ -54,6 +61,7 @@ private:
|
||||
std::unique_ptr<RateLimiter> auth_rate_limiter_;
|
||||
|
||||
static Server* instance_;
|
||||
static std::mutex instance_mutex_;
|
||||
};
|
||||
|
||||
} // namespace simple_object_storage
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user