30 |
30 |
31 class HTTPClient::HTTPClientImpl { |
31 class HTTPClient::HTTPClientImpl { |
32 public: |
32 public: |
33 CURL* curl; |
33 CURL* curl; |
34 char curlErrorBuffer[CURL_ERROR_SIZE]; |
34 char curlErrorBuffer[CURL_ERROR_SIZE]; |
|
35 std::stringstream requestBody; |
35 std::stringstream responseBody; |
36 std::stringstream responseBody; |
36 std::stringstream responseHeaders; |
37 std::stringstream responseHeaders; |
37 |
38 |
38 HTTPClientImpl(CURL* curl) : curl(curl) { |
39 HTTPClientImpl(CURL* curl) : curl(curl) { |
39 } |
40 } |
91 }; |
92 }; |
92 |
93 |
93 HTTPClient* HTTPClient::open() { |
94 HTTPClient* HTTPClient::open() { |
94 HTTPClient::HTTPClientImpl* impl = new HTTPClient::HTTPClientImpl(curl_easy_init()); |
95 HTTPClient::HTTPClientImpl* impl = new HTTPClient::HTTPClientImpl(curl_easy_init()); |
95 |
96 |
|
97 typedef size_t(*CurlReadCallback)(char*, size_t, size_t, HTTPClient::HTTPClientImpl*); |
96 typedef size_t(*CurlWriteCallback)(char*, size_t, size_t, HTTPClient::HTTPClientImpl*); |
98 typedef size_t(*CurlWriteCallback)(char*, size_t, size_t, HTTPClient::HTTPClientImpl*); |
|
99 |
|
100 // set request body callback |
|
101 curl_easy_setopt(impl->curl, CURLOPT_READDATA, impl); |
|
102 curl_easy_setopt(impl->curl, CURLOPT_READFUNCTION, (CurlReadCallback)[](char* buffer, size_t size, size_t nmemb, HTTPClient::HTTPClientImpl * impl) { |
|
103 size_t r = size * nmemb; |
|
104 ssize_t bytesRead = impl->requestBody.readsome(buffer, r); |
|
105 return (size_t) bytesRead; |
|
106 }); |
97 |
107 |
98 // set response body callback |
108 // set response body callback |
99 curl_easy_setopt(impl->curl, CURLOPT_WRITEDATA, impl); |
109 curl_easy_setopt(impl->curl, CURLOPT_WRITEDATA, impl); |
100 curl_easy_setopt(impl->curl, CURLOPT_WRITEFUNCTION, (CurlWriteCallback)[](char* buffer, size_t size, size_t nmemb, HTTPClient::HTTPClientImpl * impl)->size_t { |
110 curl_easy_setopt(impl->curl, CURLOPT_WRITEFUNCTION, (CurlWriteCallback)[](char* buffer, size_t size, size_t nmemb, HTTPClient::HTTPClientImpl * impl)->size_t { |
101 size_t r = size * nmemb; |
111 size_t r = size * nmemb; |
154 // set request headers |
164 // set request headers |
155 CurlList requestHeders; |
165 CurlList requestHeders; |
156 for (size_t i = 0; i < request.headers.size(); i += 2) requestHeders.append(request.headers[i] + ": " + request.headers[i + 1]); // TODO: validate, no CR/LF... |
166 for (size_t i = 0; i < request.headers.size(); i += 2) requestHeders.append(request.headers[i] + ": " + request.headers[i + 1]); // TODO: validate, no CR/LF... |
157 curl_easy_setopt(impl->curl, CURLOPT_HTTPHEADER, requestHeders.getList()); |
167 curl_easy_setopt(impl->curl, CURLOPT_HTTPHEADER, requestHeders.getList()); |
158 |
168 |
|
169 // store request body |
|
170 if (request.body.size()) { |
|
171 impl->requestBody = std::stringstream(request.body); |
|
172 curl_easy_setopt(impl->curl, CURLOPT_UPLOAD, 1L); |
|
173 curl_easy_setopt(impl->curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 0); |
|
174 } |
|
175 |
|
176 |
159 // clear the error buffer |
177 // clear the error buffer |
160 impl->curlErrorBuffer[0] = 0; |
178 impl->curlErrorBuffer[0] = 0; |
161 |
179 |
162 // do HTTP call |
180 // do HTTP call |
163 CURLcode result = curl_easy_perform(impl->curl); |
181 CURLcode result = curl_easy_perform(impl->curl); |