1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include "http.hpp"
#include <utility>
namespace http {
request::request(EMethod method, std::string url)
: m_url(std::move(url)) {
switch (method) {
case REQUEST_GET:
m_method = "GET";
break;
case REQUEST_POST:
m_method = "POST";
break;
case REQUEST_PATCH:
m_method = "PATCH";
break;
case REQUEST_PUT:
m_method = "PUT";
break;
case REQUEST_DELETE:
m_method = "DELETE";
break;
default:
m_method = "GET";
break;
}
prepare();
}
request::~request() {
if (m_curl != nullptr)
curl_easy_cleanup(m_curl);
if (m_header_list != nullptr)
curl_slist_free_all(m_header_list);
}
void request::set_verify_ssl(bool verify) {
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, verify ? 1L : 0L);
}
void request::set_proxy(const std::string &proxy) {
curl_easy_setopt(m_curl, CURLOPT_PROXY, proxy.c_str());
}
void request::set_header(const std::string &name, const std::string &value) {
m_header_list = curl_slist_append(m_header_list, (name + ": " + value).c_str());
}
void request::set_body(const std::string &data) {
curl_easy_setopt(m_curl, CURLOPT_COPYPOSTFIELDS, data.c_str());
}
void request::set_user_agent(const std::string &data) {
curl_easy_setopt(m_curl, CURLOPT_USERAGENT, data.c_str());
}
response request::execute() {
if (m_curl == nullptr) {
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLInit);
response.error_string = "curl pointer is null";
}
detail::check_init();
std::string str;
curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method);
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, detail::curl_write_data_callback);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &str);
curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, m_error_buf);
m_error_buf[0] = '\0';
if (m_header_list != nullptr)
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_header_list);
CURLcode result = curl_easy_perform(m_curl);
if (result != CURLE_OK) {
auto response = detail::make_response(m_url, EStatusCode::ClientErrorCURLPerform);
response.error_string = curl_easy_strerror(result);
response.error_string += " " + std::string(m_error_buf);
return response;
}
long response_code = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &response_code);
auto response = detail::make_response(m_url, response_code);
response.text = str;
return response;
}
void request::prepare() {
m_curl = curl_easy_init();
}
namespace detail {
size_t curl_write_data_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
const size_t n = size * nmemb;
static_cast<std::string *>(userdata)->append(static_cast<char *>(ptr), n);
return n;
}
response make_response(const std::string &url, int code) {
response r;
r.url = url;
r.status_code = static_cast<EStatusCode>(code);
if (code < http::EStatusCode::ClientErrorMax)
r.error = true;
return r;
}
void check_init() {
static bool initialized = false;
if (!initialized) {
curl_global_init(CURL_GLOBAL_ALL);
initialized = true;
}
}
} // namespace detail
} // namespace http
|