This commit is contained in:
217
src/server.cpp
217
src/server.cpp
@@ -154,8 +154,13 @@ void Server::setup_routes() {
|
||||
|
||||
|
||||
// Welcome page
|
||||
server_.Get("/", [](const httplib::Request&, httplib::Response& res) {
|
||||
res.set_content(welcome_page(), "text/html");
|
||||
server_.Get("/(.*)", [this](const httplib::Request& req, httplib::Response& res) {
|
||||
if (req.path == "/") {
|
||||
res.set_content(welcome_page(), "text/html");
|
||||
return;
|
||||
}
|
||||
// if the path is not /, then it's a hash or label:tag
|
||||
handle_get_object(req, res);
|
||||
});
|
||||
|
||||
server_.Get("/index.html", [](const httplib::Request&, httplib::Response& res) {
|
||||
@@ -172,6 +177,12 @@ void Server::setup_routes() {
|
||||
handle_get_hash(req, res);
|
||||
});
|
||||
|
||||
// Get version for label:tag
|
||||
server_.Get("/version/(.*)", [this](const httplib::Request& req, httplib::Response& res) {
|
||||
handle_get_version(req, res);
|
||||
});
|
||||
|
||||
|
||||
// Check if object exists by hash or label:tag
|
||||
server_.Get("/exists/(.*)", [this](const httplib::Request& req, httplib::Response& res) {
|
||||
handle_exists(req, res);
|
||||
@@ -267,45 +278,18 @@ void Server::handle_get_object(const httplib::Request& req, httplib::Response& r
|
||||
|
||||
// first check if the key matches.
|
||||
dbEntry entry;
|
||||
if (db_->get(key, entry)) {
|
||||
// got it!
|
||||
hash_str = entry.hash;
|
||||
}
|
||||
|
||||
if (hash_str.empty()) {
|
||||
if (!db_->get(key, entry)) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Object hash could not be determined"}};
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Couldn't find: " + key}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// check valid hash.
|
||||
uint64_t hash_value;
|
||||
try {
|
||||
hash_value = std::stoull(hash_str);
|
||||
} catch (const std::invalid_argument& e) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Invalid hash: " + hash_str}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream oss;
|
||||
oss << hash_value;
|
||||
if (oss.str() != hash_str) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Invalid hash: " + hash_str}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// hash is valid, safe to look up!
|
||||
|
||||
// Construct the file path using the hash string
|
||||
std::filesystem::path file_path = config_.object_store_path / oss.str();
|
||||
std::filesystem::path file_path = config_.object_store_path / entry.hash;
|
||||
if (!std::filesystem::exists(file_path) || !std::filesystem::is_regular_file(file_path)) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Object file not found for hash: " + hash_str}};
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Hash recognised, but object missing for: " + entry.hash}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
@@ -357,68 +341,23 @@ void Server::handle_get_metadata(const httplib::Request& req, httplib::Response&
|
||||
|
||||
// Check if the key is a label:tag format
|
||||
dbEntry entry;
|
||||
nlohmann::json response;
|
||||
|
||||
if (db_->get(key, entry)) {
|
||||
// Got it from label:tag, use the hash
|
||||
hash_str = entry.hash;
|
||||
}
|
||||
|
||||
// If we couldn't determine a hash
|
||||
if (hash_str.empty()) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Metadata not found for: " + key}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to interpret the key as a hash directly
|
||||
uint64_t hash_value;
|
||||
try {
|
||||
hash_value = std::stoull(hash_str);
|
||||
} catch (const std::invalid_argument& e) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Invalid hash: " + hash_str}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream oss;
|
||||
oss << hash_value;
|
||||
if (oss.str() != hash_str) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Invalid hash: " + hash_str}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// Hash is valid, look up the metadata
|
||||
std::vector<dbEntry> entries;
|
||||
if (!db_->list(entries)) {
|
||||
res.status = 500;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Failed to retrieve metadata"}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the entry with matching hash
|
||||
for (const auto& e : entries) {
|
||||
if (e.hash == hash_str) {
|
||||
try {
|
||||
nlohmann::json response = {{"result", "success"}, {"metadata", e.metadata}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
std::cerr << "Error serializing metadata for hash " << hash_str << ": " << e.what() << std::endl;
|
||||
res.status = 500;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Internal server error: Failed to serialize metadata"}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
response = {{"result", "success"}, {"metadata", entry.metadata}};
|
||||
} catch (const nlohmann::json::exception& e) {
|
||||
std::cerr << "Error serializing metadata for hash " << hash_str << ": " << e.what() << std::endl;
|
||||
res.status = 500;
|
||||
response = {{"result", "error"}, {"error", "Internal server error: Failed to serialize metadata"}};
|
||||
}
|
||||
}
|
||||
|
||||
// No entry found with this hash
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Metadata not found for hash: " + hash_str}};
|
||||
else
|
||||
{
|
||||
res.status = 404;
|
||||
response = {{"result", "error"}, {"error", "Invalid hash: " + hash_str}};
|
||||
}
|
||||
res.set_content(response.dump(), "application/json");
|
||||
}
|
||||
|
||||
@@ -431,22 +370,24 @@ std::pair<std::string, std::string> Server::parse_labeltag(const std::string& la
|
||||
}
|
||||
|
||||
void Server::handle_delete_object(const httplib::Request& req, httplib::Response& res) {
|
||||
std::map<std::string, std::string> params;
|
||||
if (!validate_write_request(req, res, {"hash"}, params)) {
|
||||
return;
|
||||
}
|
||||
dbEntry entry;
|
||||
|
||||
// Validate that the hash exists as a file
|
||||
std::filesystem::path file_path = config_.object_store_path / params["hash"];
|
||||
if (!std::filesystem::exists(file_path) || !std::filesystem::is_regular_file(file_path)) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Object not found for hash: " + params["hash"]}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::map<std::string, std::string> params;
|
||||
if (!validate_write_request(req, res, {"hash"}, params)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!db_->get(params["hash"], entry)) {
|
||||
res.status = 404;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Object not found for: " + params["hash"]}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
} // we only use sanitised data from here on out.
|
||||
|
||||
// Remove all tags that reference this hash
|
||||
if (!db_->remove_by_hash(params["hash"])) {
|
||||
if (!db_->remove_by_hash(entry.hash)) {
|
||||
res.status = 500;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Failed to remove some or all associated tags"}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
@@ -454,14 +395,17 @@ void Server::handle_delete_object(const httplib::Request& req, httplib::Response
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
try {
|
||||
std::filesystem::remove(file_path);
|
||||
} catch (const std::filesystem::filesystem_error& e) {
|
||||
std::cerr << "Error deleting object file: " << e.what() << std::endl;
|
||||
res.status = 500;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Failed to delete object file: " + std::string(e.what())}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
std::filesystem::path file_path = config_.object_store_path / entry.hash;
|
||||
if (std::filesystem::exists(file_path) && std::filesystem::is_regular_file(file_path)) {
|
||||
try {
|
||||
std::filesystem::remove(file_path);
|
||||
} catch (const std::filesystem::filesystem_error& e) {
|
||||
std::cerr << "Error deleting object file: " << e.what() << std::endl;
|
||||
res.status = 500;
|
||||
nlohmann::json response = {{"result", "error"}, {"error", "Failed to delete object file: " + std::string(e.what())}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json response = {{"result", "success"}};
|
||||
@@ -469,46 +413,35 @@ void Server::handle_delete_object(const httplib::Request& req, httplib::Response
|
||||
}
|
||||
|
||||
void Server::handle_exists(const httplib::Request& req, httplib::Response& res) {
|
||||
const auto& key = req.matches[1].str();
|
||||
nlohmann::json response;
|
||||
dbEntry entry;
|
||||
if (db_->get(key, entry)) {
|
||||
response = {{"result", "success"}, {"exists", true}};
|
||||
} else {
|
||||
response = {{"result", "success"}, {"exists", false}};
|
||||
}
|
||||
res.set_content(response.dump(), "application/json");
|
||||
}
|
||||
|
||||
void Server::handle_get_version(const httplib::Request& req, httplib::Response& res) {
|
||||
const auto& key = req.matches[1].str();
|
||||
std::string hash_str = key;
|
||||
|
||||
// Check if the key is a label:tag format
|
||||
dbEntry entry;
|
||||
if (db_->get(key, entry)) {
|
||||
// Got it from label:tag, use the hash
|
||||
hash_str = entry.hash;
|
||||
}
|
||||
|
||||
// If we couldn't determine a hash
|
||||
if (hash_str.empty()) {
|
||||
nlohmann::json response = {{"result", "success"}, {"exists", false}};
|
||||
if (!db_->get(key, entry)) {
|
||||
nlohmann::json response = {{"result", "failed"}, {"error", "Failed to get version for: " + key}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to interpret the key as a hash directly
|
||||
uint64_t hash_value;
|
||||
try {
|
||||
hash_value = std::stoull(hash_str);
|
||||
} catch (const std::invalid_argument& e) {
|
||||
nlohmann::json response = {{"result", "success"}, {"exists", false}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
nlohmann::json response;
|
||||
if (entry.metadata.contains("version")) {
|
||||
response = {{"result", "success"}, {"version", entry.metadata["version"]}};
|
||||
} else {
|
||||
response = {{"result", "failed"}, {"error", "No version found for: " + key}};
|
||||
}
|
||||
|
||||
std::stringstream oss;
|
||||
oss << hash_value;
|
||||
if (oss.str() != hash_str) {
|
||||
nlohmann::json response = {{"result", "success"}, {"exists", false}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
// Hash is valid, check if the file exists
|
||||
std::filesystem::path file_path = config_.object_store_path / oss.str();
|
||||
bool exists = std::filesystem::exists(file_path) && std::filesystem::is_regular_file(file_path);
|
||||
|
||||
nlohmann::json response = {{"result", "success"}, {"exists", exists}};
|
||||
res.set_content(response.dump(), "application/json");
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user