9 #include "NHttpRequest.h"
14 curl_global_init(CURL_GLOBAL_DEFAULT);
15 curl = curl_easy_init();
17 throw std::runtime_error(
"Error: curl_easy_init() failed");
24 curl_easy_cleanup(curl);
27 curl_slist_free_all(headers);
29 curl_global_cleanup();
33 const std::string & key_path,
const std::string & key_password_file,
36 std::ostringstream response_stream;
37 CURLcode res = request(
"GET", url,
"", response_stream, cert_path, key_path, key_password_file, insecure);
38 if (res != CURLE_OK) {
39 throw_curl_error(res);
41 return response_stream.str();
45 const std::string & cert_path,
const std::string & key_path,
46 const std::string & key_password_file,
bool insecure)
48 std::ostringstream response_stream;
49 CURLcode res = request(
"POST", url, post_data, response_stream, cert_path, key_path, key_password_file, insecure);
50 if (res != CURLE_OK) {
51 throw_curl_error(res);
53 return response_stream.str();
57 const std::string & key_password_file,
bool insecure)
59 std::ostringstream response_stream;
60 CURLcode res = request(
"HEAD", url,
"", response_stream, cert_path, key_path, key_password_file, insecure);
61 if (res != CURLE_OK) {
62 throw_curl_error(res);
66 for (
const auto & header : received_headers) {
67 if (header.find(
"HTTP/") != std::string::npos) {
68 sscanf(header.c_str(),
"HTTP/%*s %d", &http_code);
77 std::ostringstream & response_stream,
const std::string & cert_path,
78 const std::string & key_path,
const std::string & key_password_file,
81 CURLcode res = CURLE_OK;
83 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
85 received_headers.clear();
87 if (method ==
"POST") {
88 curl_easy_setopt(curl, CURLOPT_POST, 1L);
89 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
90 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
91 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_stream);
93 headers = curl_slist_append(headers,
"Content-Type: application/json");
94 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
96 else if (method ==
"HEAD") {
98 curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
99 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderCallback);
101 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
102 curl_easy_setopt(curl, CURLOPT_HEADERDATA, &received_headers);
103 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
104 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
106 else if (method ==
"GET") {
107 curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
108 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
109 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_stream);
111 headers = curl_slist_append(headers,
"Content-Type: application/json");
112 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
115 return CURLE_UNSUPPORTED_PROTOCOL;
119 if (!cert_path.empty() && !key_path.empty()) {
120 curl_easy_setopt(curl, CURLOPT_SSLCERT, cert_path.c_str());
121 curl_easy_setopt(curl, CURLOPT_SSLKEY, key_path.c_str());
124 if (!key_password_file.empty()) {
125 curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, NULL);
126 curl_easy_setopt(curl, CURLOPT_KEYPASSWD, NULL);
127 curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD,
"");
128 curl_easy_setopt(curl, CURLOPT_KEYPASSWD,
"");
130 std::ifstream passwordFile(key_password_file);
131 std::string encodedPassword;
132 if (passwordFile.is_open()) {
133 std::getline(passwordFile, encodedPassword);
134 passwordFile.close();
136 TString encoded(encodedPassword);
137 TString decoded = TBase64::Decode(encoded);
138 std::string password = decoded.Data();
141 if (!password.empty() && password.back() ==
'\r') {
145 curl_easy_setopt(curl, CURLOPT_SSLKEYPASSWD, password.c_str());
146 curl_easy_setopt(curl, CURLOPT_KEYPASSWD, password.c_str());
149 std::cerr <<
"Error: Could not open password file: " << key_password_file << std::endl;
150 return CURLE_FILE_COULDNT_READ_FILE;
157 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
158 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
163 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
164 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
167 res = curl_easy_perform(curl);
168 if (res != CURLE_OK) {
182 (
static_cast<std::ostringstream *
>(userp))->write(
static_cast<char *
>(contents), size * nmemb);
188 size_t len = size * nitems;
189 std::string header(buffer, len);
192 if (!header.empty() && header.back() ==
'\n') {
195 if (!header.empty() && header.back() ==
'\r') {
200 std::vector<std::string> * headers =
static_cast<std::vector<std::string> *
>(userdata);
202 headers->push_back(header);
210 throw std::runtime_error(std::string(
"curl error: ") + curl_easy_strerror(res));
std::string post(const std::string &url, const std::string &post_data, const std::string &cert_path="", const std::string &key_path="", const std::string &key_password_file="", bool insecure=false)
Performs an HTTP POST request.
virtual ~NHttpRequest()
Destroys the NHttpRequest instance.
std::string get(const std::string &url, const std::string &cert_path="", const std::string &key_path="", const std::string &key_password_file="", bool insecure=false)
Performs an HTTP GET request.
static size_t HeaderCallback(char *buffer, size_t size, size_t nitems, void *userdata)
Callback for handling response headers.
int head(const std::string &url, const std::string &cert_path="", const std::string &key_path="", const std::string &key_password_file="", bool insecure=false)
Performs an HTTP HEAD request.
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
Callback for writing response data.
NHttpRequest()
Constructs a new NHttpRequest instance.
CURL * curl
libcurl handle
CURLcode request(const std::string &method, const std::string &url, const std::string &data, std::ostringstream &response, const std::string &cert_path, const std::string &key_path, const std::string &key_password_file, bool insecure)
Internal method to perform an HTTP request.
void throw_curl_error(CURLcode res) const
Throws an exception if a CURL error occurs.