docs: Update 3 files
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 1m1s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m46s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 1m1s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m46s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
This commit is contained in:
@ -4,7 +4,10 @@ Based on analysis of the current codebase, the multi-server support feature need
|
|||||||
|
|
||||||
## Core Infrastructure Tasks
|
## Core Infrastructure Tasks
|
||||||
|
|
||||||
- [-] 1. Create ServerManager class and server configuration system
|
- [x] 1. Create ServerManager class and server configuration system
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -15,6 +18,10 @@ Based on analysis of the current codebase, the multi-server support feature need
|
|||||||
- _Requirements: 1.1, 1.2, 1.3, 5.1, 5.2, 5.4_
|
- _Requirements: 1.1, 1.2, 1.3, 5.1, 5.2, 5.4_
|
||||||
|
|
||||||
- [ ] 2. Enhance GetbinClient for multi-server support
|
- [ ] 2. Enhance GetbinClient for multi-server support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- Modify GetbinClient constructor to accept server list instead of hardcoded host
|
- Modify GetbinClient constructor to accept server list instead of hardcoded host
|
||||||
- Implement multi-server fallback logic for downloads
|
- Implement multi-server fallback logic for downloads
|
||||||
- Add server-specific upload and hash operations
|
- Add server-specific upload and hash operations
|
||||||
|
@ -10,20 +10,37 @@
|
|||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
const std::string GetbinClient::SERVER_HOST = "getpkg.xyz";
|
const std::string GetbinClient::DEFAULT_SERVER_HOST = "getpkg.xyz";
|
||||||
|
|
||||||
GetbinClient::GetbinClient() {
|
GetbinClient::GetbinClient(const std::vector<std::string>& servers) : servers_(servers) {
|
||||||
// Initialize CPR (done automatically, but we could add global config here)
|
// Initialize CPR (done automatically, but we could add global config here)
|
||||||
|
if (servers_.empty()) {
|
||||||
|
servers_.push_back(DEFAULT_SERVER_HOST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetbinClient::GetbinClient() : servers_({DEFAULT_SERVER_HOST}) {
|
||||||
|
// Backward compatibility constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetbinClient::getUserAgent() const {
|
std::string GetbinClient::getUserAgent() const {
|
||||||
return "getpkg/1.0";
|
return "getpkg/1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetbinClient::download(const std::string& toolName, const std::string& arch, const std::string& outPath,
|
std::string GetbinClient::buildUrl(const std::string& serverUrl, const std::string& endpoint) const {
|
||||||
|
std::string url = "https://" + serverUrl;
|
||||||
|
if (!endpoint.empty() && endpoint[0] != '/') {
|
||||||
|
url += "/";
|
||||||
|
}
|
||||||
|
url += endpoint;
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetbinClient::downloadFromServer(const std::string& serverUrl, const std::string& toolName,
|
||||||
|
const std::string& arch, const std::string& outPath,
|
||||||
ProgressCallback progressCallback) {
|
ProgressCallback progressCallback) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/object/" + toolName + ":" + arch;
|
std::string url = buildUrl(serverUrl, "/object/" + toolName + ":" + arch);
|
||||||
|
|
||||||
cpr::Session session;
|
cpr::Session session;
|
||||||
session.SetUrl(cpr::Url{url});
|
session.SetUrl(cpr::Url{url});
|
||||||
@ -52,20 +69,34 @@ bool GetbinClient::download(const std::string& toolName, const std::string& arch
|
|||||||
// Not found - this is expected for arch fallback
|
// Not found - this is expected for arch fallback
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "[GetbinClient::download] HTTP " << response.status_code << ": " << response.error.message << std::endl;
|
std::cerr << "[GetbinClient::downloadFromServer] HTTP " << response.status_code << " from " << serverUrl << ": " << response.error.message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "[GetbinClient::download] Exception: " << e.what() << std::endl;
|
std::cerr << "[GetbinClient::downloadFromServer] Exception with " << serverUrl << ": " << e.what() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetbinClient::upload(const std::string& archivePath, std::string& outUrl, std::string& outHash,
|
bool GetbinClient::download(const std::string& toolName, const std::string& arch, const std::string& outPath,
|
||||||
const std::string& token, ProgressCallback progressCallback) {
|
ProgressCallback progressCallback) {
|
||||||
|
// Multi-server fallback logic: try each server in order
|
||||||
|
for (const auto& server : servers_) {
|
||||||
|
if (downloadFromServer(server, toolName, arch, outPath, progressCallback)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, no server had the package
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetbinClient::upload(const std::string& serverUrl, const std::string& archivePath,
|
||||||
|
std::string& outUrl, std::string& outHash, const std::string& token,
|
||||||
|
ProgressCallback progressCallback) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/upload";
|
std::string url = buildUrl(serverUrl, "/upload");
|
||||||
|
|
||||||
cpr::Session session;
|
cpr::Session session;
|
||||||
session.SetUrl(cpr::Url{url});
|
session.SetUrl(cpr::Url{url});
|
||||||
@ -110,7 +141,7 @@ bool GetbinClient::upload(const std::string& archivePath, std::string& outUrl, s
|
|||||||
try {
|
try {
|
||||||
auto resp_json = json::parse(response.text);
|
auto resp_json = json::parse(response.text);
|
||||||
if (resp_json.contains("hash") && resp_json.contains("result") && resp_json["result"] == "success") {
|
if (resp_json.contains("hash") && resp_json.contains("result") && resp_json["result"] == "success") {
|
||||||
outUrl = "https://" + SERVER_HOST + "/object/" + resp_json["hash"].get<std::string>();
|
outUrl = buildUrl(serverUrl, "/object/" + resp_json["hash"].get<std::string>());
|
||||||
outHash = resp_json["hash"].get<std::string>();
|
outHash = resp_json["hash"].get<std::string>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -125,7 +156,7 @@ bool GetbinClient::upload(const std::string& archivePath, std::string& outUrl, s
|
|||||||
return !outHash.empty();
|
return !outHash.empty();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "[GetbinClient::upload] HTTP " << response.status_code << ": " << response.error.message << std::endl;
|
std::cerr << "[GetbinClient::upload] HTTP " << response.status_code << " to " << serverUrl << ": " << response.error.message << std::endl;
|
||||||
if (!response.text.empty()) {
|
if (!response.text.empty()) {
|
||||||
std::cerr << "[GetbinClient::upload] Response: " << response.text << std::endl;
|
std::cerr << "[GetbinClient::upload] Response: " << response.text << std::endl;
|
||||||
}
|
}
|
||||||
@ -133,14 +164,24 @@ bool GetbinClient::upload(const std::string& archivePath, std::string& outUrl, s
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "[GetbinClient::upload] Exception: " << e.what() << std::endl;
|
std::cerr << "[GetbinClient::upload] Exception with " << serverUrl << ": " << e.what() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetbinClient::getHash(const std::string& toolName, const std::string& arch, std::string& outHash) {
|
bool GetbinClient::upload(const std::string& archivePath, std::string& outUrl, std::string& outHash,
|
||||||
|
const std::string& token, ProgressCallback progressCallback) {
|
||||||
|
// Backward compatibility: use first server
|
||||||
|
if (servers_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return upload(servers_[0], archivePath, outUrl, outHash, token, progressCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetbinClient::getHash(const std::string& serverUrl, const std::string& toolName,
|
||||||
|
const std::string& arch, std::string& outHash) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/hash/" + toolName + ":" + arch;
|
std::string url = buildUrl(serverUrl, "/hash/" + toolName + ":" + arch);
|
||||||
|
|
||||||
auto response = cpr::Get(cpr::Url{url},
|
auto response = cpr::Get(cpr::Url{url},
|
||||||
cpr::Header{{"User-Agent", getUserAgent()}},
|
cpr::Header{{"User-Agent", getUserAgent()}},
|
||||||
@ -168,19 +209,63 @@ bool GetbinClient::getHash(const std::string& toolName, const std::string& arch,
|
|||||||
// Not found - this is expected for non-existent tools/archs
|
// Not found - this is expected for non-existent tools/archs
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "[GetbinClient::getHash] HTTP " << response.status_code << ": " << response.error.message << std::endl;
|
std::cerr << "[GetbinClient::getHash] HTTP " << response.status_code << " from " << serverUrl << ": " << response.error.message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "[GetbinClient::getHash] Exception: " << e.what() << std::endl;
|
std::cerr << "[GetbinClient::getHash] Exception with " << serverUrl << ": " << e.what() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetbinClient::getHash(const std::string& toolName, const std::string& arch, std::string& outHash) {
|
||||||
|
// Multi-server fallback: try each server in order
|
||||||
|
for (const auto& server : servers_) {
|
||||||
|
if (getHash(server, toolName, arch, outHash)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, no server had the package
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetbinClient::findPackageServer(const std::string& toolName, const std::string& arch,
|
||||||
|
std::string& foundServer) const {
|
||||||
|
// Check each server to see which one has the package
|
||||||
|
for (const auto& server : servers_) {
|
||||||
|
try {
|
||||||
|
std::string url = buildUrl(server, "/hash/" + toolName + ":" + arch);
|
||||||
|
|
||||||
|
auto response = cpr::Get(cpr::Url{url},
|
||||||
|
cpr::Header{{"User-Agent", getUserAgent()}},
|
||||||
|
cpr::Timeout{10000}, // 10 seconds
|
||||||
|
cpr::VerifySsl{true});
|
||||||
|
|
||||||
|
if (response.status_code == 200) {
|
||||||
|
// Package found on this server
|
||||||
|
foundServer = server;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Continue to next server if 404 or other error
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// Continue to next server on exception
|
||||||
|
std::cerr << "[GetbinClient::findPackageServer] Exception with " << server << ": " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package not found on any server
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetbinClient::deleteObject(const std::string& hash, const std::string& token) {
|
bool GetbinClient::deleteObject(const std::string& hash, const std::string& token) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/deleteobject?hash=" + hash;
|
// Use first server for backward compatibility
|
||||||
|
if (servers_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string url = buildUrl(servers_[0], "/deleteobject?hash=" + hash);
|
||||||
|
|
||||||
auto response = cpr::Get(cpr::Url{url},
|
auto response = cpr::Get(cpr::Url{url},
|
||||||
cpr::Header{
|
cpr::Header{
|
||||||
@ -208,7 +293,11 @@ bool GetbinClient::deleteObject(const std::string& hash, const std::string& toke
|
|||||||
|
|
||||||
bool GetbinClient::listPackages(std::vector<std::string>& outPackages) {
|
bool GetbinClient::listPackages(std::vector<std::string>& outPackages) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/dir";
|
// Use first server for backward compatibility
|
||||||
|
if (servers_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string url = buildUrl(servers_[0], "/dir");
|
||||||
|
|
||||||
auto response = cpr::Get(cpr::Url{url},
|
auto response = cpr::Get(cpr::Url{url},
|
||||||
cpr::Header{{"User-Agent", getUserAgent()}},
|
cpr::Header{{"User-Agent", getUserAgent()}},
|
||||||
@ -271,7 +360,11 @@ bool GetbinClient::listPackages(std::vector<std::string>& outPackages) {
|
|||||||
|
|
||||||
bool GetbinClient::listAllEntries(std::vector<std::pair<std::string, std::vector<std::string>>>& outEntries) {
|
bool GetbinClient::listAllEntries(std::vector<std::pair<std::string, std::vector<std::string>>>& outEntries) {
|
||||||
try {
|
try {
|
||||||
std::string url = "https://" + SERVER_HOST + "/dir";
|
// Use first server for backward compatibility
|
||||||
|
if (servers_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string url = buildUrl(servers_[0], "/dir");
|
||||||
|
|
||||||
auto response = cpr::Get(cpr::Url{url},
|
auto response = cpr::Get(cpr::Url{url},
|
||||||
cpr::Header{{"User-Agent", getUserAgent()}},
|
cpr::Header{{"User-Agent", getUserAgent()}},
|
||||||
|
@ -5,21 +5,53 @@
|
|||||||
|
|
||||||
class GetbinClient {
|
class GetbinClient {
|
||||||
public:
|
public:
|
||||||
|
// Constructor accepting server list for multi-server support
|
||||||
|
GetbinClient(const std::vector<std::string>& servers);
|
||||||
|
|
||||||
|
// Backward compatibility constructor (uses default server)
|
||||||
GetbinClient();
|
GetbinClient();
|
||||||
|
|
||||||
// Progress callback: (downloaded_bytes, total_bytes) -> should_continue
|
// Progress callback: (downloaded_bytes, total_bytes) -> should_continue
|
||||||
using ProgressCallback = std::function<bool(size_t, size_t)>;
|
using ProgressCallback = std::function<bool(size_t, size_t)>;
|
||||||
|
|
||||||
|
// Multi-server download with fallback logic
|
||||||
bool download(const std::string& toolName, const std::string& arch, const std::string& outPath,
|
bool download(const std::string& toolName, const std::string& arch, const std::string& outPath,
|
||||||
ProgressCallback progressCallback = nullptr);
|
ProgressCallback progressCallback = nullptr);
|
||||||
|
|
||||||
|
// Server-specific download
|
||||||
|
bool downloadFromServer(const std::string& serverUrl, const std::string& toolName,
|
||||||
|
const std::string& arch, const std::string& outPath,
|
||||||
|
ProgressCallback progressCallback = nullptr);
|
||||||
|
|
||||||
|
// Server-specific upload
|
||||||
|
bool upload(const std::string& serverUrl, const std::string& archivePath,
|
||||||
|
std::string& outUrl, std::string& outHash, const std::string& token,
|
||||||
|
ProgressCallback progressCallback = nullptr);
|
||||||
|
|
||||||
|
// Backward compatibility upload (uses first server)
|
||||||
bool upload(const std::string& archivePath, std::string& outUrl, std::string& outHash, const std::string& token,
|
bool upload(const std::string& archivePath, std::string& outUrl, std::string& outHash, const std::string& token,
|
||||||
ProgressCallback progressCallback = nullptr);
|
ProgressCallback progressCallback = nullptr);
|
||||||
|
|
||||||
|
// Server-specific hash retrieval
|
||||||
|
bool getHash(const std::string& serverUrl, const std::string& toolName,
|
||||||
|
const std::string& arch, std::string& outHash);
|
||||||
|
|
||||||
|
// Multi-server hash retrieval with fallback
|
||||||
bool getHash(const std::string& toolName, const std::string& arch, std::string& outHash);
|
bool getHash(const std::string& toolName, const std::string& arch, std::string& outHash);
|
||||||
|
|
||||||
|
// Find which server has a specific package
|
||||||
|
bool findPackageServer(const std::string& toolName, const std::string& arch,
|
||||||
|
std::string& foundServer) const;
|
||||||
|
|
||||||
|
// Legacy methods (use first server for backward compatibility)
|
||||||
bool deleteObject(const std::string& hash, const std::string& token);
|
bool deleteObject(const std::string& hash, const std::string& token);
|
||||||
bool listPackages(std::vector<std::string>& outPackages);
|
bool listPackages(std::vector<std::string>& outPackages);
|
||||||
bool listAllEntries(std::vector<std::pair<std::string, std::vector<std::string>>>& outEntries);
|
bool listAllEntries(std::vector<std::pair<std::string, std::vector<std::string>>>& outEntries);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const std::string SERVER_HOST;
|
static const std::string DEFAULT_SERVER_HOST;
|
||||||
|
std::vector<std::string> servers_;
|
||||||
|
|
||||||
std::string getUserAgent() const;
|
std::string getUserAgent() const;
|
||||||
|
std::string buildUrl(const std::string& serverUrl, const std::string& endpoint) const;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user