summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorEgor Pugin <egor.pugin@gmail.com>2018-07-04 19:11:03 +0300
committerEgor Pugin <egor.pugin@gmail.com>2018-07-04 19:11:03 +0300
commit95f86f4ce18e65d45894d5a130c4bdaf8ecbaac5 (patch)
tree0235eaef9d2dcd9725c1eb9d24c8de0201ba6fcc /src/net
parent7f388398bbcff916f5507770af727ef9ad59f33d (diff)
Implement CurlHttpClient.
Diffstat (limited to 'src/net')
-rw-r--r--src/net/HttpClient.cpp66
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
+
}