140 lines
4.6 KiB
C++
140 lines
4.6 KiB
C++
#include "minio_uploader.h"
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#if __has_include(<curl/curl.h>)
|
|
#include <curl/curl.h>
|
|
#define HAS_CURL 1
|
|
#else
|
|
#define HAS_CURL 0
|
|
#endif
|
|
|
|
namespace rk3588 {
|
|
|
|
namespace {
|
|
|
|
std::string GetEnvOrDefault(const std::string& env_name, const std::string& default_val) {
|
|
(void)env_name;
|
|
// Handle ${ENV_VAR} syntax
|
|
if (default_val.size() > 3 && default_val.substr(0, 2) == "${" &&
|
|
default_val.back() == '}') {
|
|
std::string var_name = default_val.substr(2, default_val.size() - 3);
|
|
const char* val = std::getenv(var_name.c_str());
|
|
return val ? std::string(val) : "";
|
|
}
|
|
return default_val;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool MinioUploader::Init(const SimpleJson& config) {
|
|
endpoint_ = config.ValueOr<std::string>("endpoint", "http://localhost:9000");
|
|
bucket_ = config.ValueOr<std::string>("bucket", "alarms");
|
|
region_ = config.ValueOr<std::string>("region", "us-east-1");
|
|
|
|
std::string ak = config.ValueOr<std::string>("access_key", "");
|
|
std::string sk = config.ValueOr<std::string>("secret_key", "");
|
|
|
|
access_key_ = GetEnvOrDefault("MINIO_ACCESS_KEY", ak);
|
|
secret_key_ = GetEnvOrDefault("MINIO_SECRET_KEY", sk);
|
|
|
|
use_ssl_ = endpoint_.find("https://") == 0;
|
|
|
|
if (access_key_.empty() || secret_key_.empty()) {
|
|
std::cerr << "[MinioUploader] warning: access_key or secret_key not set\n";
|
|
}
|
|
|
|
std::cout << "[MinioUploader] initialized, endpoint=" << endpoint_
|
|
<< " bucket=" << bucket_ << "\n";
|
|
return true;
|
|
}
|
|
|
|
UploadResult MinioUploader::Upload(const std::string& key,
|
|
const uint8_t* data,
|
|
size_t size,
|
|
const std::string& content_type) {
|
|
UploadResult result;
|
|
|
|
#if HAS_CURL
|
|
// Simple S3 PUT request (works with MinIO)
|
|
// For production, use proper AWS4 signing
|
|
|
|
std::string url = endpoint_;
|
|
if (url.back() != '/') url += '/';
|
|
url += bucket_ + "/" + key;
|
|
|
|
CURL* curl = curl_easy_init();
|
|
if (!curl) {
|
|
result.error = "curl_easy_init failed";
|
|
return result;
|
|
}
|
|
|
|
struct curl_slist* headers = nullptr;
|
|
std::string ct = content_type.empty() ? "application/octet-stream" : content_type;
|
|
headers = curl_slist_append(headers, ("Content-Type: " + ct).c_str());
|
|
|
|
// Simple auth (MinIO supports this for internal use)
|
|
// For proper S3 compatibility, implement AWS4 signing
|
|
if (!access_key_.empty()) {
|
|
// This is a simplified approach - real implementation should use AWS4 signing
|
|
std::string auth = "Authorization: AWS " + access_key_ + ":" + secret_key_;
|
|
headers = curl_slist_append(headers, auth.c_str());
|
|
}
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(size));
|
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
|
|
|
// Set up data to send
|
|
struct ReadData {
|
|
const uint8_t* data;
|
|
size_t remaining;
|
|
} read_data{data, size};
|
|
|
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION,
|
|
+[](char* buffer, size_t s, size_t n, void* userp) -> size_t {
|
|
auto* rd = static_cast<ReadData*>(userp);
|
|
size_t to_copy = std::min(s * n, rd->remaining);
|
|
if (to_copy > 0) {
|
|
std::memcpy(buffer, rd->data, to_copy);
|
|
rd->data += to_copy;
|
|
rd->remaining -= to_copy;
|
|
}
|
|
return to_copy;
|
|
});
|
|
curl_easy_setopt(curl, CURLOPT_READDATA, &read_data);
|
|
|
|
CURLcode res = curl_easy_perform(curl);
|
|
if (res != CURLE_OK) {
|
|
result.error = curl_easy_strerror(res);
|
|
} else {
|
|
long http_code = 0;
|
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
|
if (http_code >= 200 && http_code < 300) {
|
|
result.success = true;
|
|
result.url = url;
|
|
} else {
|
|
result.error = "HTTP " + std::to_string(http_code);
|
|
}
|
|
}
|
|
|
|
curl_slist_free_all(headers);
|
|
curl_easy_cleanup(curl);
|
|
#else
|
|
// Stub for Windows
|
|
std::cout << "[MinioUploader] would upload " << size << " bytes to "
|
|
<< endpoint_ << "/" << bucket_ << "/" << key << "\n";
|
|
result.success = true;
|
|
result.url = endpoint_ + "/" + bucket_ + "/" + key;
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace rk3588
|