diff options
author | Egor Pugin <egor.pugin@gmail.com> | 2018-07-04 19:11:03 +0300 |
---|---|---|
committer | Egor Pugin <egor.pugin@gmail.com> | 2018-07-04 19:11:03 +0300 |
commit | 95f86f4ce18e65d45894d5a130c4bdaf8ecbaac5 (patch) | |
tree | 0235eaef9d2dcd9725c1eb9d24c8de0201ba6fcc /src/net | |
parent | 7f388398bbcff916f5507770af727ef9ad59f33d (diff) |
Implement CurlHttpClient.
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/HttpClient.cpp | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/net/HttpClient.cpp b/src/net/HttpClient.cpp index 340eb1e..479b72a 100644 --- a/src/net/HttpClient.cpp +++ b/src/net/HttpClient.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Oleg Morozenkov + * Copyright (c) 2018 Egor Pugin * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,12 +31,12 @@ using namespace boost::asio::ip; namespace TgBot { -HttpClient& HttpClient::getInstance() { - static HttpClient result; +BoostHttpClient& BoostHttpClient::getInstance() { + static BoostHttpClient result; return result; } -string HttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) { +string BoostHttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) const { ssl::context context(ssl::context::sslv23); context.set_default_verify_paths(); @@ -87,4 +88,63 @@ string HttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) { return HttpParser::getInstance().parseResponse(response); } +#ifdef HAVE_CURL + +CurlHttpClient::CurlHttpClient() { + curlSettings = curl_easy_init(); +} + +CurlHttpClient::~CurlHttpClient() { + curl_easy_cleanup(curlSettings); +} + +CurlHttpClient& CurlHttpClient::getInstance() { + static CurlHttpClient result; + return result; +} + +static size_t curl_write_string(char *ptr, size_t size, size_t nmemb, void *userdata) +{ + std::string &s = *(std::string *)userdata; + auto read = size * nmemb; + s.append(ptr, ptr + read); + return read; +}; + +string CurlHttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) const { + // Copy settings for each call because we change CURLOPT_URL and other stuff. + // This also protects multithreaded case. + auto curl = curl_easy_duphandle(curlSettings); + + auto u = url.protocol + "://" + url.host + url.path; + curl_easy_setopt(curl, CURLOPT_URL, u.c_str()); + + if (!args.empty()) + { + std::string data; + for (auto &a : args) + data += a.name + "=" + a.value + "&"; + data.resize(data.size() - 1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); + } + + std::string response; + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_string); + + auto res = curl_easy_perform(curl); + long http_code; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + curl_easy_cleanup(curl); + + if (res != CURLE_OK) + throw std::runtime_error("curl error: "s + curl_easy_strerror(res)); + if (http_code != 200) + throw std::runtime_error("curl request returned with code = " + std::to_string(http_code)); + + return HttpParser::getInstance().parseResponse(response); +} + +#endif + } |