diff --git a/push/include/prometheus/gateway.h b/push/include/prometheus/gateway.h index e6acd0f0..b65cfb28 100644 --- a/push/include/prometheus/gateway.h +++ b/push/include/prometheus/gateway.h @@ -58,6 +58,12 @@ class PROMETHEUS_CPP_PUSH_EXPORT Gateway { // Delete metrics from the given pushgateway (for configured instance labels). std::future AsyncDeleteForInstance(); + /// \brief Add a custom HTTP header. + /// + /// \param header custom header in the form "key:value". + /// \return true on success, otherwise false + bool AddHttpHeader(const std::string& header); + private: std::string jobUri_; std::string labels_; diff --git a/push/src/curl_wrapper.cc b/push/src/curl_wrapper.cc index 767e10f1..8481c47a 100644 --- a/push/src/curl_wrapper.cc +++ b/push/src/curl_wrapper.cc @@ -22,12 +22,18 @@ CurlWrapper::CurlWrapper(const std::string& username, throw std::runtime_error("Cannot initialize easy curl!"); } + optHttpHeader_ = curl_slist_append(nullptr, CONTENT_TYPE); + if (!optHttpHeader_) { + throw std::runtime_error("Cannot append the header of the content type"); + } + if (!username.empty()) { auth_ = username + ":" + password; } } CurlWrapper::~CurlWrapper() { + curl_slist_free_all(optHttpHeader_); curl_easy_cleanup(curl_); curl_global_cleanup(); } @@ -39,9 +45,7 @@ int CurlWrapper::performHttpRequest(HttpMethod method, const std::string& uri, curl_easy_reset(curl_); curl_easy_setopt(curl_, CURLOPT_URL, uri.c_str()); - curl_slist* header_chunk = nullptr; - header_chunk = curl_slist_append(header_chunk, CONTENT_TYPE); - curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_chunk); + curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, optHttpHeader_); if (!body.empty()) { curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, body.size()); @@ -77,8 +81,6 @@ int CurlWrapper::performHttpRequest(HttpMethod method, const std::string& uri, long response_code; curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &response_code); - curl_slist_free_all(header_chunk); - if (curl_error != CURLE_OK) { return -curl_error; } @@ -86,5 +88,16 @@ int CurlWrapper::performHttpRequest(HttpMethod method, const std::string& uri, return response_code; } +bool CurlWrapper::addHttpHeader(const std::string& header) { + std::lock_guard lock{mutex_}; + auto updated_header = curl_slist_append(optHttpHeader_, header.c_str()); + if (!updated_header) { + return false; + } + + optHttpHeader_ = updated_header; + return true; +} + } // namespace detail } // namespace prometheus diff --git a/push/src/curl_wrapper.h b/push/src/curl_wrapper.h index df20d6bb..e62c62f8 100644 --- a/push/src/curl_wrapper.h +++ b/push/src/curl_wrapper.h @@ -21,11 +21,13 @@ class CurlWrapper { int performHttpRequest(HttpMethod method, const std::string& uri, const std::string& body); + bool addHttpHeader(const std::string& header); private: CURL* curl_; std::string auth_; std::mutex mutex_; + curl_slist* optHttpHeader_; }; } // namespace detail diff --git a/push/src/gateway.cc b/push/src/gateway.cc index 7d61266c..e1ec9d5d 100644 --- a/push/src/gateway.cc +++ b/push/src/gateway.cc @@ -164,4 +164,8 @@ void Gateway::CleanupStalePointers( std::end(collectables)); } +bool Gateway::AddHttpHeader(const std::string& header) { + return curlWrapper_->addHttpHeader(header); +} + } // namespace prometheus