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::string requestBody; |
36 std::stringstream responseBody; |
36 std::stringstream responseBody; |
37 std::stringstream responseHeaders; |
37 std::stringstream responseHeaders; |
38 |
38 |
39 HTTPClientImpl(CURL* curl) : curl(curl) { |
39 HTTPClientImpl(CURL* curl) : curl(curl) { |
40 } |
40 } |
92 }; |
92 }; |
93 |
93 |
94 HTTPClient* HTTPClient::open() { |
94 HTTPClient* HTTPClient::open() { |
95 HTTPClient::HTTPClientImpl* impl = new HTTPClient::HTTPClientImpl(curl_easy_init()); |
95 HTTPClient::HTTPClientImpl* impl = new HTTPClient::HTTPClientImpl(curl_easy_init()); |
96 |
96 |
97 typedef size_t(*CurlReadCallback)(char*, size_t, size_t, HTTPClient::HTTPClientImpl*); |
|
98 typedef size_t(*CurlWriteCallback)(char*, size_t, size_t, HTTPClient::HTTPClientImpl*); |
97 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 }); |
|
107 |
98 |
108 // set response body callback |
99 // set response body callback |
109 curl_easy_setopt(impl->curl, CURLOPT_WRITEDATA, impl); |
100 curl_easy_setopt(impl->curl, CURLOPT_WRITEDATA, impl); |
110 curl_easy_setopt(impl->curl, CURLOPT_WRITEFUNCTION, (CurlWriteCallback)[](char* buffer, size_t size, size_t nmemb, HTTPClient::HTTPClientImpl * impl)->size_t { |
101 curl_easy_setopt(impl->curl, CURLOPT_WRITEFUNCTION, (CurlWriteCallback)[](char* buffer, size_t size, size_t nmemb, HTTPClient::HTTPClientImpl * impl)->size_t { |
111 size_t r = size * nmemb; |
102 size_t r = size * nmemb; |
164 // set request headers |
155 // set request headers |
165 CurlList requestHeders; |
156 CurlList requestHeders; |
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 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... |
167 curl_easy_setopt(impl->curl, CURLOPT_HTTPHEADER, requestHeders.getList()); |
158 curl_easy_setopt(impl->curl, CURLOPT_HTTPHEADER, requestHeders.getList()); |
168 |
159 |
169 // store request body |
160 // set request body |
170 if (request.body.size()) { |
161 if (request.body.size()) { |
171 impl->requestBody = std::stringstream(request.body); |
162 impl->requestBody = request.body; |
172 curl_easy_setopt(impl->curl, CURLOPT_UPLOAD, 1L); |
163 curl_off_t requestBodySize = impl->requestBody.size(); |
173 curl_easy_setopt(impl->curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 0); |
164 curl_easy_setopt(impl->curl, CURLOPT_POSTFIELDS, impl->requestBody.c_str()); |
|
165 curl_easy_setopt(impl->curl, CURLOPT_POSTFIELDSIZE_LARGE, requestBodySize); |
174 } |
166 } |
175 |
167 |
176 |
168 |
177 // clear the error buffer |
169 // clear the error buffer |
178 impl->curlErrorBuffer[0] = 0; |
170 impl->curlErrorBuffer[0] = 0; |