11#ifndef _AUROSTD_XHTTP_CPP_
12#define _AUROSTD_XHTTP_CPP_
30#include <curl/header.h>
42using std::stringstream;
45#define _DEBUG_XHTTP_ false
59 size_t writeData2string(
void* ptr,
size_t size,
size_t nmemb,
void* data) {
60 static_cast<std::string*
>(data)->append(
static_cast<char*
>(ptr), size * nmemb);
73 size_t writeData2File(
void* ptr,
size_t size,
size_t nmemb,
void* stream) {
74 const size_t written = fwrite(ptr, size, nmemb,
static_cast<FILE*
>(stream));
75 if (written != nmemb * size) {
76 std::stringstream message;
77 message <<
"error " << errno <<
": " << strerror(errno);
89 void checkCURLStatus(
const CURLcode& status,
const std::array<char, CURL_ERROR_SIZE>& errbuf) {
90 if (status == CURLE_OK) {
93 const string message(errbuf.data());
107 void httpGetBase(
const string& url,
const std::string& filename, std::string& output,
long& response_code, std::map<std::string, std::string>& header) {
108 const bool LDEBUG = (
false ||
XHOST.DEBUG);
113 const std::string agent =
"AFLOW/" + string(AFLOW_VERSION);
115 CURL* handle = curl_easy_init();
117 struct curl_header* raw_header =
nullptr;
118 struct curl_header* prev_header =
nullptr;
120 std::array<char, CURL_ERROR_SIZE> errbuf;
123 CURLcode status = CURLE_OK;
127 curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf.data());
129 status = curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
130 checkCURLStatus(status, errbuf);
132 status = curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
133 checkCURLStatus(status, errbuf);
135 status = curl_easy_setopt(handle, CURLOPT_USERAGENT, agent.c_str());
136 checkCURLStatus(status, errbuf);
139 status = curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L);
140 checkCURLStatus(status, errbuf);
144 status = curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L);
145 checkCURLStatus(status, errbuf);
148 status = curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 1L);
149 checkCURLStatus(status, errbuf);
151 if (filename.empty()) {
153 status = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeData2string);
154 checkCURLStatus(status, errbuf);
156 status = curl_easy_setopt(handle, CURLOPT_WRITEDATA, &output);
157 checkCURLStatus(status, errbuf);
159 status = curl_easy_perform(handle);
160 checkCURLStatus(status, errbuf);
163 status = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeData2File);
164 checkCURLStatus(status, errbuf);
167 if (FILE* output_file = fopen(filename_clean.c_str(),
"wb")) {
169 status = curl_easy_setopt(handle, CURLOPT_WRITEDATA, output_file);
170 checkCURLStatus(status, errbuf);
172 status = curl_easy_perform(handle);
173 checkCURLStatus(status, errbuf);
175 if (
const int r = fclose(output_file); r != 0) {
176 const string message =
"Unable to close file " + filename_clean;
181 const string message =
"Unable to open file " + filename_clean;
186 status = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
187 checkCURLStatus(status, errbuf);
192 constexpr unsigned int header_origin = CURLH_HEADER | CURLH_1XX | CURLH_TRAILER;
193 while ((raw_header = curl_easy_nextheader(handle, header_origin, -1, prev_header)) !=
nullptr) {
194 header.insert({raw_header->name, raw_header->value});
195 prev_header = raw_header;
198 curl_easy_cleanup(handle);
208 void httpGet(
const string& url, std::string& output,
long& response_code, std::map<std::string, std::string>& header) {
209 httpGetBase(url,
"", output, response_code, header);
217 void httpGetFile(
const string& url,
const std::string& filename,
long& response_code, std::map<std::string, std::string>& header) {
218 std::string discarded_output;
219 httpGetBase(url, filename, discarded_output, response_code, header);
227 long response_code = -1;
228 std::map<std::string, std::string> header;
229 httpGet(url, output, response_code, header);
230 return response_code;
238 long response_code = -1;
239 std::map<std::string, std::string> header;
240 httpGet(url, output, response_code, header);
241 return response_code;
249 long httpGetStatus(
const std::string& url, std::string& output, std::map<std::string, std::string>& header) {
250 long response_code = -1;
251 httpGet(url, output, response_code, header);
252 return response_code;
261 long httpGetStatus(
const std::string& host,
const std::string& path,
const std::string& query, std::string& output) {
262 const std::string url =
"http://" + host +
"/" + path + query;
263 long response_code = -1;
264 std::map<std::string, std::string> header;
265 httpGet(url, output, response_code, header);
266 return response_code;
275 long httpGetStatus(
const std::string& host,
const std::string& path,
const std::string& query, std::string& output, std::map<std::string, std::string>& header) {
276 const std::string url =
"http://" + host +
"/" + path + query;
277 long response_code = -1;
278 httpGet(url, output, response_code, header);
279 return response_code;
287 long response_code = -1;
288 std::map<std::string, std::string> header;
290 httpGet(url, output, response_code, header);
298 std::string
httpGet(
const std::string& url,
long& response_code) {
300 std::map<std::string, std::string> header;
303 httpGet(url, output, response_code, header);
312 std::string
httpGet(
const std::string& url,
long& response_code, std::map<std::string, std::string>& header) {
315 httpGet(url, output, response_code, header);
324 long response_code = -1;
325 std::map<std::string, std::string> header;
327 return response_code;
335 long httpGetFileStatus(
const std::string& url,
const std::string& filename, std::map<std::string, std::string>& header) {
336 long response_code = -1;
338 return response_code;
346 template <
typename utype>
size_t httpGetTokens(
const string& url, vector<utype>& tokens,
const string& delimiters) {
347 const bool LDEBUG = (
false ||
XHOST.DEBUG);
354 if (status != 200 || content.empty()) {
358 vector<string> stokens;
360 for (
const string& stoken : stokens) {
361 if (!stoken.empty()) {
366 cerr <<
__AFLOW_FUNC__ <<
"Loaded " << tokens.size() <<
" tokens from " << url << endl;
368 return tokens.size();
371#define AST_TEMPLATE(utype) template size_t httpGetTokens(const string&, std::vector<utype>&, const string&);
386 return httpGet(url, response_code, header);
389 httpGetFile(url, temp_file, response_code, header);
400 std::map<std::string, std::string> header;
409 std::map<std::string, std::string> header;
410 long response_code = -1;
422 const char* allowed =
423 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
424 "abcdefghijklmnopqrstuvwxyz"
430 std::stringstream output;
432 cerr <<
__AFLOW_FUNC__ <<
" Escaping '" << work_str <<
"'" << std::endl;
435 while (!work_str.empty()) {
436 pos = std::strspn(work_str.c_str(), allowed);
437 to_replace = work_str[pos];
438 if (to_replace < 0) {
441 output << work_str.substr(0, pos) <<
"%" << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2) << to_replace;
443 cerr <<
" Match '" << work_str[pos] <<
"' (%" << std::uppercase << std::hex << std::setfill(
'0') << to_replace << std::dec <<
")" << std::endl;
445 work_str.erase(0, pos + 1);
This file contains the preprocessor macros to ensure a proper instantiation of all aurostd functions.
#define AST_GEN_1(type_selection)
autogenerate 1D code based on AST_TEMPLATE
std::string httpGetCompressedFileContent(const string &url, long &response_code, std::map< std::string, std::string > &header)
get the content of a file from the web, decompress locally if needed
string TmpFileCreate(const string &identifier, const string &tmpdir, const bool hidden)
create a string pointing to the location of a unique temp file
void httpGetFile(const string &url, const std::string &filename, long &response_code, std::map< std::string, std::string > &header)
get a web resource as file
string CleanFileName(const string &fileIN)
cleans file names from obvious things
uint string2tokens(const string &str, vector< string > &tokens, const string &delimiters=" ", bool consecutive=false) __xprototype
size_t httpGetTokens(const string &url, vector< utype > &tokens, const string &delimiters)
get the data split into tokens
string httpPercentEncodingFull(string work_str)
Fully percent encode a string.
long httpGetStatus(const std::string &url)
Retrieve data from an url.
utype string2utype(const string &from, const uint base=10)
void httpGet(const string &url, std::string &output, long &response_code, std::map< std::string, std::string > &header)
get a web resource as string
size_t compressfile2string(const string &FileNameIN, string &content)
compressed file to string
string GetFileExtension(const string &FileName)
returns the file extension
long httpGetFileStatus(const std::string &url, const std::string &filename)
Download data as file.