This commit is contained in:
parent
ede75f5565
commit
1fce6fc0b4
@ -1,4 +1,32 @@
|
|||||||
#include "http_utils.hpp"
|
#include "http_utils.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
static std::string find_ca_certificates() {
|
||||||
|
// Common CA certificate locations across different Linux distributions
|
||||||
|
const std::vector<std::string> ca_paths = {
|
||||||
|
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Raspbian
|
||||||
|
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL/CentOS
|
||||||
|
"/etc/ssl/ca-bundle.pem", // OpenSUSE
|
||||||
|
"/etc/pki/tls/cert.pem", // Fedora/RHEL alternative
|
||||||
|
"/etc/ssl/certs/ca-bundle.crt", // Some distros
|
||||||
|
"/etc/ssl/cert.pem", // Alpine Linux
|
||||||
|
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
|
||||||
|
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7+
|
||||||
|
"/etc/ca-certificates/extracted/tls-ca-bundle.pem" // Arch Linux
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& path : ca_paths) {
|
||||||
|
std::ifstream file(path);
|
||||||
|
if (file.good()) {
|
||||||
|
file.close();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https, double timeout_seconds) {
|
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https, double timeout_seconds) {
|
||||||
HttpResponse result{0, "", false};
|
HttpResponse result{0, "", false};
|
||||||
@ -14,6 +42,105 @@ HttpResponse http_get(const std::string& url, const std::string& path, bool use_
|
|||||||
&loop
|
&loop
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Configure SSL certificates for HTTPS
|
||||||
|
if (use_https) {
|
||||||
|
std::string ca_path = find_ca_certificates();
|
||||||
|
if (!ca_path.empty()) {
|
||||||
|
std::cerr << "Debug: Found CA certificates at: " << ca_path << std::endl;
|
||||||
|
// Use addSSLConfigs with proper parameter names for OpenSSL
|
||||||
|
std::vector<std::pair<std::string, std::string>> sslConfigs;
|
||||||
|
sslConfigs.push_back({"VerifyCAFile", ca_path});
|
||||||
|
client->addSSLConfigs(sslConfigs);
|
||||||
|
} else {
|
||||||
|
// If no CA certificates found, print warning but continue
|
||||||
|
std::cerr << "Warning: No system CA certificates found. SSL verification may fail." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto req = drogon::HttpRequest::newHttpRequest();
|
||||||
|
req->setMethod(drogon::Get);
|
||||||
|
req->setPath(path);
|
||||||
|
|
||||||
|
client->sendRequest(req, [&](drogon::ReqResult res, const drogon::HttpResponsePtr &resp) {
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (res == drogon::ReqResult::Ok && resp) {
|
||||||
|
result.status_code = resp->statusCode();
|
||||||
|
result.body = resp->body();
|
||||||
|
result.success = true;
|
||||||
|
} else {
|
||||||
|
result.status_code = 0;
|
||||||
|
result.body = "";
|
||||||
|
result.success = false;
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
cv.notify_one();
|
||||||
|
loop.quit();
|
||||||
|
}, timeout_seconds);
|
||||||
|
|
||||||
|
loop.loop();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
|
cv.wait(lock, [&] { return done; });
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.join();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpResponse http_get_with_ssl(const std::string& url, const std::string& path, const HttpClientSSLConfig& ssl_config, double timeout_seconds) {
|
||||||
|
HttpResponse result{0, "", false};
|
||||||
|
bool done = false;
|
||||||
|
std::mutex mtx;
|
||||||
|
std::condition_variable cv;
|
||||||
|
|
||||||
|
std::thread worker([&]() {
|
||||||
|
trantor::EventLoop loop;
|
||||||
|
|
||||||
|
// Create HTTPS client with SSL configuration options
|
||||||
|
auto client = drogon::HttpClient::newHttpClient(
|
||||||
|
"https://" + url,
|
||||||
|
&loop,
|
||||||
|
ssl_config.use_old_tls,
|
||||||
|
ssl_config.validate_cert
|
||||||
|
);
|
||||||
|
|
||||||
|
// Configure client certificate if provided
|
||||||
|
if (!ssl_config.cert_path.empty() && !ssl_config.key_path.empty()) {
|
||||||
|
client->setCertPath(ssl_config.cert_path, ssl_config.key_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure SSL settings
|
||||||
|
std::vector<std::pair<std::string, std::string>> finalSslConfigs = ssl_config.ssl_configs;
|
||||||
|
|
||||||
|
// Set CA certificates path if not explicitly disabled
|
||||||
|
if (ssl_config.validate_cert) {
|
||||||
|
// Check if cafile is provided in ssl_configs
|
||||||
|
bool ca_path_set = false;
|
||||||
|
for (const auto& config : ssl_config.ssl_configs) {
|
||||||
|
if (config.first == "cafile" || config.first == "CAfile" ||
|
||||||
|
config.first == "VerifyCAFile") {
|
||||||
|
ca_path_set = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no cafile provided, use system certificates
|
||||||
|
if (!ca_path_set) {
|
||||||
|
std::string ca_path = find_ca_certificates();
|
||||||
|
if (!ca_path.empty()) {
|
||||||
|
finalSslConfigs.push_back({"VerifyCAFile", ca_path});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all SSL configurations at once
|
||||||
|
if (!finalSslConfigs.empty()) {
|
||||||
|
client->addSSLConfigs(finalSslConfigs);
|
||||||
|
}
|
||||||
|
|
||||||
auto req = drogon::HttpRequest::newHttpRequest();
|
auto req = drogon::HttpRequest::newHttpRequest();
|
||||||
req->setMethod(drogon::Get);
|
req->setMethod(drogon::Get);
|
||||||
req->setPath(path);
|
req->setPath(path);
|
||||||
|
@ -13,5 +13,17 @@ struct HttpResponse {
|
|||||||
bool success;
|
bool success;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SSL configuration options for HTTP client
|
||||||
|
struct HttpClientSSLConfig {
|
||||||
|
std::string cert_path; // Client certificate path
|
||||||
|
std::string key_path; // Client key path
|
||||||
|
bool validate_cert = true; // Whether to validate server certificate
|
||||||
|
bool use_old_tls = false; // Enable TLS 1.0/1.1
|
||||||
|
std::vector<std::pair<std::string, std::string>> ssl_configs; // Additional SSL_CONF_cmd options
|
||||||
|
};
|
||||||
|
|
||||||
// Utility function for blocking HTTP GET requests
|
// Utility function for blocking HTTP GET requests
|
||||||
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https = false, double timeout_seconds = 10.0);
|
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https = false, double timeout_seconds = 10.0);
|
||||||
|
|
||||||
|
// Utility function for blocking HTTP GET requests with SSL configuration
|
||||||
|
HttpResponse http_get_with_ssl(const std::string& url, const std::string& path, const HttpClientSSLConfig& ssl_config, double timeout_seconds = 10.0);
|
@ -15,7 +15,7 @@ int main() {
|
|||||||
std::cout << "Retrieving IP address..." << std::endl;
|
std::cout << "Retrieving IP address..." << std::endl;
|
||||||
|
|
||||||
// Use the utility function for HTTP GET
|
// Use the utility function for HTTP GET
|
||||||
auto response = http_get("ipinfo.io", "/ip", false, 10.0);
|
auto response = http_get("ipinfo.io", "/ip", true, 10.0);
|
||||||
|
|
||||||
ASSERT(response.success && response.status_code == 200, "Failed to get IP");
|
ASSERT(response.success && response.status_code == 200, "Failed to get IP");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user