'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
|
} // namespace simple_object_storage
|
@@ -21,7 +21,6 @@ public:
|
|||||||
ADD_METHOD_TO(HttpController::getObject, "/object/{1}", {drogon::Get});
|
ADD_METHOD_TO(HttpController::getObject, "/object/{1}", {drogon::Get});
|
||||||
ADD_METHOD_TO(HttpController::getRoot, "/", {drogon::Get});
|
ADD_METHOD_TO(HttpController::getRoot, "/", {drogon::Get});
|
||||||
ADD_METHOD_TO(HttpController::getAny, "/{1}", {drogon::Get});
|
ADD_METHOD_TO(HttpController::getAny, "/{1}", {drogon::Get});
|
||||||
ADD_METHOD_TO(HttpController::putNotFound, "/{1}", {drogon::Put});
|
|
||||||
METHOD_LIST_END
|
METHOD_LIST_END
|
||||||
|
|
||||||
void getIndex(const drogon::HttpRequestPtr &req,
|
void getIndex(const drogon::HttpRequestPtr &req,
|
||||||
@@ -68,10 +67,6 @@ public:
|
|||||||
void getAny(const drogon::HttpRequestPtr &req,
|
void getAny(const drogon::HttpRequestPtr &req,
|
||||||
std::function<void(const drogon::HttpResponsePtr &)> &&callback,
|
std::function<void(const drogon::HttpResponsePtr &)> &&callback,
|
||||||
const std::string &path);
|
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
|
} // namespace simple_object_storage
|
@@ -46,6 +46,25 @@ void PutHandler::handle_put_object(const drogon::HttpRequestPtr& req, std::funct
|
|||||||
return;
|
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
|
// Parse the multipart form data
|
||||||
drogon::MultiPartParser fileParser;
|
drogon::MultiPartParser fileParser;
|
||||||
if (fileParser.parse(req) != 0) {
|
if (fileParser.parse(req) != 0) {
|
||||||
@@ -169,20 +188,20 @@ void PutHandler::handle_put_object(const drogon::HttpRequestPtr& req, std::funct
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write file content to temporary file
|
temp_file.close();
|
||||||
auto fileContent = fileData->fileContent();
|
|
||||||
if (!temp_file.write(fileContent.data(), fileContent.size())) {
|
// 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);
|
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->setBody(response.dump());
|
||||||
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
|
||||||
temp_file.close();
|
|
||||||
std::filesystem::remove(temp_path);
|
std::filesystem::remove(temp_path);
|
||||||
callback(resp);
|
callback(resp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_file.close();
|
|
||||||
|
|
||||||
// Ensure the temporary file is removed even if errors occur
|
// Ensure the temporary file is removed even if errors occur
|
||||||
ScopeFileDeleter temp_file_deleter(temp_path);
|
ScopeFileDeleter temp_file_deleter(temp_path);
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
namespace simple_object_storage {
|
namespace simple_object_storage {
|
||||||
|
|
||||||
Server* Server::instance_ = nullptr;
|
Server* Server::instance_ = nullptr;
|
||||||
|
std::mutex Server::instance_mutex_;
|
||||||
|
|
||||||
|
|
||||||
bool Server::init_db() {
|
bool Server::init_db() {
|
||||||
@@ -145,6 +146,11 @@ bool Server::start() {
|
|||||||
drogon::app().addListener(config_.host, config_.port);
|
drogon::app().addListener(config_.host, config_.port);
|
||||||
drogon::app().setThreadNum(16);
|
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
|
// Start the server
|
||||||
try {
|
try {
|
||||||
drogon::app().run();
|
drogon::app().run();
|
||||||
@@ -165,9 +171,11 @@ void Server::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Server::setup_routes() {
|
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) {
|
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
|
// Handle OPTIONS requests for CORS preflight
|
||||||
@@ -175,6 +183,7 @@ void Server::setup_routes() {
|
|||||||
std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
|
std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
|
||||||
handle_cors_preflight(req, std::move(callback));
|
handle_cors_preflight(req, std::move(callback));
|
||||||
}, {}, "OPTIONS");
|
}, {}, "OPTIONS");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handle_cors_preflight(const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr &)>&& callback) {
|
void Server::handle_cors_preflight(const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr &)>&& callback) {
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
@@ -20,8 +21,14 @@ public:
|
|||||||
Server(const ServerConfig& config);
|
Server(const ServerConfig& config);
|
||||||
~Server();
|
~Server();
|
||||||
|
|
||||||
static Server* getInstance() { return instance_; }
|
static Server* getInstance() {
|
||||||
static void setInstance(Server* server) { instance_ = server; }
|
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();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
@@ -54,6 +61,7 @@ private:
|
|||||||
std::unique_ptr<RateLimiter> auth_rate_limiter_;
|
std::unique_ptr<RateLimiter> auth_rate_limiter_;
|
||||||
|
|
||||||
static Server* instance_;
|
static Server* instance_;
|
||||||
|
static std::mutex instance_mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simple_object_storage
|
} // namespace simple_object_storage
|
@@ -414,5 +414,14 @@ if ! curl -s -H "Authorization: Bearer ${WRITE_TOKEN}" "${HOSTURL}/deleteobject?
|
|||||||
die "failed to delete ${TODELHASH}"
|
die "failed to delete ${TODELHASH}"
|
||||||
fi
|
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"
|
title "ALL TESTS PASSED"
|
||||||
|
Reference in New Issue
Block a user