mirror of
https://github.com/openappsec/openappsec.git
synced 2025-08-14 05:45:57 +03:00
sync code
This commit is contained in:
parent
da20943c09
commit
e4747ede14
@ -0,0 +1,200 @@
|
|||||||
|
#include "fog_connection.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cereal/archives/json.hpp>
|
||||||
|
#include <cereal/types/vector.hpp>
|
||||||
|
#include <cereal/types/map.hpp>
|
||||||
|
#include <cereal/types/string.hpp>
|
||||||
|
#include "debug.h"
|
||||||
|
#include "internal/curl_http_client.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_NGINX_MANAGER);
|
||||||
|
|
||||||
|
// Helper function to check if HTTPResponse indicates success
|
||||||
|
bool
|
||||||
|
isSuccessfulResponse(const HTTPResponse& response)
|
||||||
|
{
|
||||||
|
HTTPStatusCode code = response.getHTTPStatusCode();
|
||||||
|
return (code == HTTPStatusCode::HTTP_OK ||
|
||||||
|
code == HTTPStatusCode::HTTP_NO_CONTENT ||
|
||||||
|
code == HTTPStatusCode::HTTP_MULTI_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
FogConnection::FogConnection(const string& token, const string& fog_address)
|
||||||
|
: var_token(token), var_fog(fog_address), curl_client(std::make_unique<CurlHttpClient>()) {}
|
||||||
|
|
||||||
|
void
|
||||||
|
FogConnection::setProxy(const string& hosts)
|
||||||
|
{
|
||||||
|
curl_client->setProxy(hosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<void>
|
||||||
|
FogConnection::getCredentials()
|
||||||
|
{
|
||||||
|
AgentRegistrationRequest request;
|
||||||
|
AgentRegistrationRequest::AuthData auth;
|
||||||
|
|
||||||
|
auth.authenticationMethod = "token";
|
||||||
|
auth.data = var_token;
|
||||||
|
|
||||||
|
request.authenticationData.push_back(auth);
|
||||||
|
request.metaData.agentName = "ConfCollector";
|
||||||
|
request.metaData.agentType = "Embedded";
|
||||||
|
request.metaData.platform = "linux";
|
||||||
|
request.metaData.architecture = "x86";
|
||||||
|
request.metaData.additionalMetaData["agentVendor"] = "nginx-conf-collector";
|
||||||
|
|
||||||
|
stringstream ss_req;
|
||||||
|
{
|
||||||
|
cereal::JSONOutputArchive ar(ss_req);
|
||||||
|
request.serialize(ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "Registration JSON: " << ss_req.str();
|
||||||
|
|
||||||
|
string url = var_fog + "/agents";
|
||||||
|
map<string, string> headers = {{"Content-Type", "application/json"},
|
||||||
|
{"User-Agent", "Infinity Next (a7030abf93a4c13)"}};
|
||||||
|
|
||||||
|
auto response = curl_client->post(url, ss_req.str(), headers);
|
||||||
|
|
||||||
|
dbgTrace(D_NGINX_MANAGER)
|
||||||
|
<< "Register agent response code: "
|
||||||
|
<< static_cast<int>(response.getHTTPStatusCode())
|
||||||
|
<< ", body: "
|
||||||
|
<< response.getBody();
|
||||||
|
|
||||||
|
if (!isSuccessfulResponse(response)) {
|
||||||
|
return genError("Failed to register agent: HTTP "
|
||||||
|
+ to_string(static_cast<int>(response.getHTTPStatusCode()))
|
||||||
|
+ " - "
|
||||||
|
+ response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.getBody().find("referenceId") != string::npos) {
|
||||||
|
return genError("Registration failed: " + response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AgentRegistrationResponse reg_response;
|
||||||
|
stringstream ss_res(response.getBody());
|
||||||
|
cereal::JSONInputArchive ar(ss_res);
|
||||||
|
reg_response.serialize(ar);
|
||||||
|
|
||||||
|
agent_id = reg_response.agentId;
|
||||||
|
clientId = reg_response.clientId;
|
||||||
|
clientSecret = reg_response.clientSecret;
|
||||||
|
tenant_id = reg_response.tenantId;
|
||||||
|
profile_id = reg_response.profileId;
|
||||||
|
} catch (const exception& e) {
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "Failed to parse registration response: " << response.getBody();
|
||||||
|
return genError("Failed to parse registration response: " + string(e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<void>
|
||||||
|
FogConnection::getJWT()
|
||||||
|
{
|
||||||
|
TokenRequest request;
|
||||||
|
request.login = clientId;
|
||||||
|
request.password = clientSecret;
|
||||||
|
|
||||||
|
stringstream ss_req;
|
||||||
|
{
|
||||||
|
cereal::JSONOutputArchive ar(ss_req);
|
||||||
|
ar(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
string url = var_fog + "/oauth/token?grant_type=client_credentials";
|
||||||
|
map<string, string> headers = {{"Content-Type", "application/json"},
|
||||||
|
{"User-Agent", "Infinity Next (a7030abf93a4c13)"}};
|
||||||
|
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "get JWT JSON: " << ss_req.str();
|
||||||
|
|
||||||
|
curl_client->setBasicAuth(clientId, clientSecret);
|
||||||
|
curl_client->authEnabled(true);
|
||||||
|
auto response = curl_client->post(url, ss_req.str(), headers);
|
||||||
|
|
||||||
|
dbgTrace(D_NGINX_MANAGER)
|
||||||
|
<< "get JWT response code: "
|
||||||
|
<< static_cast<int>(response.getHTTPStatusCode())
|
||||||
|
<< ", body: "
|
||||||
|
<< response.getBody();
|
||||||
|
|
||||||
|
if (!isSuccessfulResponse(response)) {
|
||||||
|
return genError("Failed to get JWT: HTTP "
|
||||||
|
+ to_string(static_cast<int>(response.getHTTPStatusCode()))
|
||||||
|
+ " - "
|
||||||
|
+ response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.getBody().find("referenceId") != string::npos) {
|
||||||
|
return genError("JWT request failed: " + response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
TokenResponse token_response;
|
||||||
|
stringstream ss_res(response.getBody());
|
||||||
|
cereal::JSONInputArchive ar(ss_res);
|
||||||
|
token_response.serialize(ar);
|
||||||
|
|
||||||
|
ra_token = token_response.access_token;
|
||||||
|
} catch (const exception& e) {
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "Failed to parse JWT response: " << response.getBody();
|
||||||
|
return genError("Failed to parse JWT response: " + string(e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<void>
|
||||||
|
FogConnection::uploadNginxConfig(const string& config_file_path)
|
||||||
|
{
|
||||||
|
if (tenant_id.empty() || profile_id.empty() || ra_token.empty()) {
|
||||||
|
return genError("Missing required data for upload: tenant_id, profile_id, or ra_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
ifstream file(config_file_path, ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
return genError("Cannot open file: " + config_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
string file_content((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (file_content.empty()) {
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "Warning: Uploading empty file content from " << config_file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string upload_url = var_fog + "/agents-core/storage/" + tenant_id + "/nginx/" + profile_id + "/1/nginx.conf";
|
||||||
|
map<string, string> headers = {
|
||||||
|
{"Authorization", "Bearer " + ra_token},
|
||||||
|
{"Content-Type", "text/plain"},
|
||||||
|
{"User-Agent", "Infinity Next (a7030abf93a4c13)"}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto response = curl_client->put(upload_url, file_content, headers);
|
||||||
|
|
||||||
|
dbgTrace(D_NGINX_MANAGER)
|
||||||
|
<< "Upload status code: "
|
||||||
|
<< static_cast<int>(response.getHTTPStatusCode())
|
||||||
|
<< ", body: "
|
||||||
|
<< response.getBody();
|
||||||
|
|
||||||
|
if (!isSuccessfulResponse(response)) {
|
||||||
|
return genError("Upload failed: HTTP "
|
||||||
|
+ to_string(static_cast<int>(response.getHTTPStatusCode()))
|
||||||
|
+ " - "
|
||||||
|
+ response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __FOG_CONNECTION_H__
|
||||||
|
#define __FOG_CONNECTION_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include "services_sdk/interfaces/i_http_client.h"
|
||||||
|
#include "req_res_objects.h"
|
||||||
|
#include "maybe_res.h"
|
||||||
|
|
||||||
|
class FogConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FogConnection(const std::string& token, const std::string& fog_address);
|
||||||
|
|
||||||
|
void setProxy(const std::string& hosts);
|
||||||
|
Maybe<void> getCredentials();
|
||||||
|
Maybe<void> getJWT();
|
||||||
|
Maybe<void> uploadNginxConfig(const std::string& config_file_path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string var_token;
|
||||||
|
std::string var_fog;
|
||||||
|
std::string agent_id;
|
||||||
|
std::string tenant_id;
|
||||||
|
std::string profile_id;
|
||||||
|
std::string ra_token;
|
||||||
|
std::string clientId;
|
||||||
|
std::string clientSecret;
|
||||||
|
std::unique_ptr<I_HttpClient> curl_client;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __FOG_CONNECTION_H__
|
@ -0,0 +1,132 @@
|
|||||||
|
#ifndef __REQ_RES_OBJECTS_H__
|
||||||
|
#define __REQ_RES_OBJECTS_H__
|
||||||
|
|
||||||
|
#include "cereal/archives/json.hpp"
|
||||||
|
#include "cereal/types/string.hpp"
|
||||||
|
#include "cereal/types/vector.hpp"
|
||||||
|
#include "cereal/types/map.hpp"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_NGINX_MANAGER);
|
||||||
|
|
||||||
|
struct AgentRegistrationRequest
|
||||||
|
{
|
||||||
|
struct AuthData
|
||||||
|
{
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("authenticationMethod", authenticationMethod));
|
||||||
|
ar(cereal::make_nvp("data", data));
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in AuthData: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string authenticationMethod;
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MetaData
|
||||||
|
{
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("agentName", agentName));
|
||||||
|
ar(cereal::make_nvp("agentType", agentType));
|
||||||
|
ar(cereal::make_nvp("platform", platform));
|
||||||
|
ar(cereal::make_nvp("architecture", architecture));
|
||||||
|
for (const auto& pair : additionalMetaData) {
|
||||||
|
ar(cereal::make_nvp(pair.first.c_str(), pair.second));
|
||||||
|
}
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in MetaData: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string agentName;
|
||||||
|
std::string agentType;
|
||||||
|
std::string platform;
|
||||||
|
std::string architecture;
|
||||||
|
std::map<std::string, std::string> additionalMetaData;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("authenticationData", authenticationData));
|
||||||
|
ar(cereal::make_nvp("metaData", metaData));
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in AgentRegistrationRequest: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AuthData> authenticationData;
|
||||||
|
MetaData metaData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TokenRequest
|
||||||
|
{
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("login", login));
|
||||||
|
ar(cereal::make_nvp("password", password));
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in TokenRequest: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string login;
|
||||||
|
std::string password;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AgentRegistrationResponse
|
||||||
|
{
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("agentId", agentId));
|
||||||
|
ar(cereal::make_nvp("clientId", clientId));
|
||||||
|
ar(cereal::make_nvp("clientSecret", clientSecret));
|
||||||
|
ar(cereal::make_nvp("tenantId", tenantId));
|
||||||
|
ar(cereal::make_nvp("profileId", profileId));
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in AgentRegistrationResponse: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string agentId;
|
||||||
|
std::string clientId;
|
||||||
|
std::string clientSecret;
|
||||||
|
std::string tenantId;
|
||||||
|
std::string profileId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TokenResponse
|
||||||
|
{
|
||||||
|
template<class Archive>
|
||||||
|
void serialize(Archive& ar)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ar(cereal::make_nvp("access_token", access_token));
|
||||||
|
} catch (const cereal::Exception &e) {
|
||||||
|
dbgWarning(D_NGINX_MANAGER) << "Serialization error in TokenResponse: " << e.what();
|
||||||
|
ar.setNextName(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string access_token;
|
||||||
|
};
|
||||||
|
#endif
|
10
core/curl_http_client/CMakeLists.txt
Executable file
10
core/curl_http_client/CMakeLists.txt
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
find_package(CURL REQUIRED)
|
||||||
|
|
||||||
|
include_directories(${CURL_INCLUDE_DIRS})
|
||||||
|
link_directories(${CURL_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
add_library(curl_http_client STATIC
|
||||||
|
curl_http_client.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(curl_http_client ${CURL_LIBRARIES})
|
183
core/curl_http_client/curl_http_client.cc
Normal file
183
core/curl_http_client/curl_http_client.cc
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#include "curl_http_client.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include "messaging/messaging_enums.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
USE_DEBUG_FLAG(D_NGINX_MANAGER);
|
||||||
|
|
||||||
|
// Helper function to convert HTTP status code to HTTPStatusCode enum
|
||||||
|
HTTPStatusCode convertStatusCode(long code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
case 200: return HTTPStatusCode::HTTP_OK;
|
||||||
|
case 204: return HTTPStatusCode::HTTP_NO_CONTENT;
|
||||||
|
case 207: return HTTPStatusCode::HTTP_MULTI_STATUS;
|
||||||
|
case 400: return HTTPStatusCode::HTTP_BAD_REQUEST;
|
||||||
|
case 401: return HTTPStatusCode::HTTP_UNAUTHORIZED;
|
||||||
|
case 403: return HTTPStatusCode::HTTP_FORBIDDEN;
|
||||||
|
case 404: return HTTPStatusCode::HTTP_NOT_FOUND;
|
||||||
|
case 405: return HTTPStatusCode::HTTP_METHOD_NOT_ALLOWED;
|
||||||
|
case 407: return HTTPStatusCode::HTTP_PROXY_AUTHENTICATION_REQUIRED;
|
||||||
|
case 408: return HTTPStatusCode::HTTP_REQUEST_TIME_OUT;
|
||||||
|
case 413: return HTTPStatusCode::HTTP_PAYLOAD_TOO_LARGE;
|
||||||
|
case 429: return HTTPStatusCode::HTTP_TOO_MANY_REQUESTS;
|
||||||
|
case 500: return HTTPStatusCode::HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
case 501: return HTTPStatusCode::HTTP_NOT_IMPLEMENTED;
|
||||||
|
case 502: return HTTPStatusCode::HTTP_BAD_GATEWAY;
|
||||||
|
case 503: return HTTPStatusCode::HTTP_SERVICE_UNABAILABLE;
|
||||||
|
case 504: return HTTPStatusCode::HTTP_GATEWAY_TIMEOUT;
|
||||||
|
case 505: return HTTPStatusCode::HTTP_VERSION_NOT_SUPPORTED;
|
||||||
|
case 506: return HTTPStatusCode::HTTP_VARIANT_ALSO_NEGOTIATES;
|
||||||
|
case 507: return HTTPStatusCode::HTTP_INSUFFICIENT_STORAGE;
|
||||||
|
case 508: return HTTPStatusCode::HTTP_LOOP_DETECTED;
|
||||||
|
case 510: return HTTPStatusCode::HTTP_NOT_EXTENDED;
|
||||||
|
case 511: return HTTPStatusCode::HTTP_NETWORK_AUTHENTICATION_REQUIRED;
|
||||||
|
default: return HTTPStatusCode::NO_HTTP_RESPONSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurlHttpClient::CurlHttpClient(): auth_enabled(false)
|
||||||
|
{
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurlHttpClient::~CurlHttpClient()
|
||||||
|
{
|
||||||
|
curl_global_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurlHttpClient::setProxy(const string& hosts)
|
||||||
|
{
|
||||||
|
no_proxy_hosts = hosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurlHttpClient::setBasicAuth(const string& username, const string& password)
|
||||||
|
{
|
||||||
|
this->username = username;
|
||||||
|
this->password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CurlHttpClient::authEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
auth_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::get(const string& url, const map<string, string>& headers)
|
||||||
|
{
|
||||||
|
return perform_request("GET", url, "", headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::post(const string& url, const string& data, const map<string, string>& headers)
|
||||||
|
{
|
||||||
|
return perform_request("POST", url, data, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::put(const string& url, const string& body, const map<string, string>& headers)
|
||||||
|
{
|
||||||
|
return perform_request("PUT", url, body, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::patch(const string& url, const string& body, const map<string, string>& headers)
|
||||||
|
{
|
||||||
|
return perform_request("PATCH", url, body, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::del(const string& url, const map<string, string>& headers)
|
||||||
|
{
|
||||||
|
return perform_request("DELETE", url, "", headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
CurlHttpClient::WriteCallback(void *contents, size_t size, size_t nmemb, string *userp)
|
||||||
|
{
|
||||||
|
size_t totalSize = size * nmemb;
|
||||||
|
userp->append(static_cast<char *>(contents), totalSize);
|
||||||
|
return totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
CurlHttpClient::perform_request(
|
||||||
|
const string& method,
|
||||||
|
const string& url,
|
||||||
|
const string& body,
|
||||||
|
const map<string, string>& headers
|
||||||
|
)
|
||||||
|
{
|
||||||
|
string response_body;
|
||||||
|
long status_code = 0;
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
if (!curl) {
|
||||||
|
return HTTPResponse(HTTPStatusCode::NO_HTTP_RESPONSE, "Failed to initialize curl");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct curl_slist *header_list = nullptr;
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_body);
|
||||||
|
|
||||||
|
if (!no_proxy_hosts.empty()) {
|
||||||
|
dbgTrace(D_NGINX_MANAGER) << "Using proxy url: " << no_proxy_hosts;
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROXY, no_proxy_hosts.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
|
||||||
|
if (!username.empty() && !password.empty() && auth_enabled) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method == "POST") {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
|
||||||
|
} else if (method == "PUT") {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
|
||||||
|
} else if (method == "PATCH") {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
|
||||||
|
} else if (method == "DELETE") {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &header_pair : headers) {
|
||||||
|
string header_str = header_pair.first + ": " + header_pair.second;
|
||||||
|
header_list = curl_slist_append(header_list, header_str.c_str());
|
||||||
|
}
|
||||||
|
if (header_list) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
CURLcode res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if (res == CURLE_OK) {
|
||||||
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||||
|
} else {
|
||||||
|
response_body = "curl_easy_perform() failed: " + string(curl_easy_strerror(res));
|
||||||
|
status_code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header_list) {
|
||||||
|
curl_slist_free_all(header_list);
|
||||||
|
}
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
return HTTPResponse(convertStatusCode(status_code), response_body);
|
||||||
|
}
|
76
core/include/internal/curl_http_client.h
Normal file
76
core/include/internal/curl_http_client.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#ifndef __CURL_HTTP_CLIENT_H__
|
||||||
|
#define __CURL_HTTP_CLIENT_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include "messaging/http_response.h"
|
||||||
|
#include "i_http_client.h"
|
||||||
|
|
||||||
|
class CurlHttpClient : public I_HttpClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CurlHttpClient();
|
||||||
|
~CurlHttpClient();
|
||||||
|
|
||||||
|
void setProxy(const std::string& hosts) override;
|
||||||
|
void setBasicAuth(const std::string& username, const std::string& password) override;
|
||||||
|
void authEnabled(bool enabled) override;
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
get(
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) override;
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
post(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& data,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) override;
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
put(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) override; HTTPResponse
|
||||||
|
patch(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) override;
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
del(
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static size_t
|
||||||
|
WriteCallback(
|
||||||
|
void *contents,
|
||||||
|
size_t size,
|
||||||
|
size_t nmemb,
|
||||||
|
std::string *userp
|
||||||
|
);
|
||||||
|
|
||||||
|
HTTPResponse
|
||||||
|
perform_request(
|
||||||
|
const std::string& method,
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const std::map<std::string, std::string>& headers
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string no_proxy_hosts;
|
||||||
|
bool auth_enabled;
|
||||||
|
std::string username;
|
||||||
|
std::string password;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __CURL_HTTP_CLIENT_H__
|
||||||
|
|
50
core/include/services_sdk/interfaces/i_http_client.h
Normal file
50
core/include/services_sdk/interfaces/i_http_client.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef __I_HTTP_CLIENT_H__
|
||||||
|
#define __I_HTTP_CLIENT_H__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "messaging/http_response.h"
|
||||||
|
|
||||||
|
class I_HttpClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~I_HttpClient() = default;
|
||||||
|
virtual void setProxy(const std::string& hosts) = 0;
|
||||||
|
virtual void setBasicAuth(const std::string& username, const std::string& password) = 0;
|
||||||
|
virtual void authEnabled(bool enabled) = 0;
|
||||||
|
|
||||||
|
virtual HTTPResponse
|
||||||
|
get(
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HTTPResponse
|
||||||
|
post(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& data,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HTTPResponse
|
||||||
|
put(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HTTPResponse
|
||||||
|
patch(
|
||||||
|
const std::string& url,
|
||||||
|
const std::string& body,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HTTPResponse
|
||||||
|
del(
|
||||||
|
const std::string& url,
|
||||||
|
const std::map<std::string, std::string>& headers = {}
|
||||||
|
) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __I_HTTP_CLIENT_H__
|
Loading…
x
Reference in New Issue
Block a user