comparison Core/HttpClient.cpp @ 2040:6ea2e264ca50

retrieval of HTTP headers in answers within HttpClient
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 21 Jun 2016 16:34:30 +0200
parents e7e1858d9504
children 9f61ca1e3eb3
comparison
equal deleted inserted replaced
2039:e33e0ae51d7b 2040:6ea2e264ca50
34 #include "HttpClient.h" 34 #include "HttpClient.h"
35 35
36 #include "Toolbox.h" 36 #include "Toolbox.h"
37 #include "OrthancException.h" 37 #include "OrthancException.h"
38 #include "Logging.h" 38 #include "Logging.h"
39 #include "ChunkedBuffer.h"
39 40
40 #include <string.h> 41 #include <string.h>
41 #include <curl/curl.h> 42 #include <curl/curl.h>
42 #include <boost/algorithm/string/predicate.hpp> 43 #include <boost/algorithm/string/predicate.hpp>
43 #include <boost/thread/mutex.hpp> 44 #include <boost/thread/mutex.hpp>
216 } 217 }
217 218
218 219
219 static size_t CurlBodyCallback(void *buffer, size_t size, size_t nmemb, void *payload) 220 static size_t CurlBodyCallback(void *buffer, size_t size, size_t nmemb, void *payload)
220 { 221 {
221 std::string& target = *(static_cast<std::string*>(payload)); 222 ChunkedBuffer& target = *(static_cast<ChunkedBuffer*>(payload));
222 223
223 size_t length = size * nmemb; 224 size_t length = size * nmemb;
224 if (length == 0) 225 if (length == 0)
226 {
225 return 0; 227 return 0;
226 228 }
227 size_t pos = target.size(); 229 else
228 230 {
229 target.resize(pos + length); 231 target.AddChunk(buffer, length);
230 memcpy(&target.at(pos), buffer, length); 232 return length;
231 233 }
232 return length; 234 }
235
236
237 static size_t CurlHeaderCallback(void *buffer, size_t size, size_t nmemb, void *payload)
238 {
239 HttpClient::HttpHeaders& headers = *(static_cast<HttpClient::HttpHeaders*>(payload));
240
241 size_t length = size * nmemb;
242 if (length == 0)
243 {
244 return 0;
245 }
246 else
247 {
248 std::string s(reinterpret_cast<const char*>(buffer), length);
249 std::size_t colon = s.find(':');
250 std::size_t eol = s.find("\r\n");
251 if (colon != std::string::npos &&
252 eol != std::string::npos)
253 {
254 std::string tmp;
255 Toolbox::ToLowerCase(tmp, s.substr(0, colon));
256 std::string key = Toolbox::StripSpaces(tmp);
257
258 if (!key.empty())
259 {
260 std::string value = Toolbox::StripSpaces(s.substr(colon + 1, eol));
261 headers[key] = value;
262 }
263 }
264
265 return length;
266 }
233 } 267 }
234 268
235 269
236 void HttpClient::Setup() 270 void HttpClient::Setup()
237 { 271 {
352 pimpl_->userHeaders_ = NULL; 386 pimpl_->userHeaders_ = NULL;
353 } 387 }
354 } 388 }
355 389
356 390
357 bool HttpClient::ApplyInternal(std::string& answer) 391 bool HttpClient::ApplyInternal(std::string& answer,
392 HttpHeaders* headers)
358 { 393 {
359 answer.clear(); 394 answer.clear();
360 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); 395 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str()));
361 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); 396
397 if (headers == NULL)
398 {
399 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, NULL));
400 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, NULL));
401 }
402 else
403 {
404 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, &CurlHeaderCallback));
405 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, headers));
406 }
362 407
363 #if ORTHANC_SSL_ENABLED == 1 408 #if ORTHANC_SSL_ENABLED == 1
364 // Setup HTTPS-related options 409 // Setup HTTPS-related options
365 410
366 if (verifyPeers_) 411 if (verifyPeers_)
518 563
519 // Do the actual request 564 // Do the actual request
520 CURLcode code; 565 CURLcode code;
521 long status = 0; 566 long status = 0;
522 567
568 ChunkedBuffer buffer;
569 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &buffer));
570
523 if (boost::starts_with(url_, "https://")) 571 if (boost::starts_with(url_, "https://"))
524 { 572 {
525 code = OrthancHttpClientPerformSSL(pimpl_->curl_, &status); 573 code = OrthancHttpClientPerformSSL(pimpl_->curl_, &status);
526 } 574 }
527 else 575 else
541 lastStatus_ = static_cast<HttpStatus>(status); 589 lastStatus_ = static_cast<HttpStatus>(status);
542 } 590 }
543 591
544 bool success = (status >= 200 && status < 300); 592 bool success = (status >= 200 && status < 300);
545 593
546 if (!success) 594 if (success)
547 { 595 {
596 buffer.Flatten(answer);
597 }
598 else
599 {
600 answer.clear();
548 LOG(INFO) << "Error in HTTP request, received HTTP status " << status 601 LOG(INFO) << "Error in HTTP request, received HTTP status " << status
549 << " (" << EnumerationToString(lastStatus_) << ")"; 602 << " (" << EnumerationToString(lastStatus_) << ")";
550 } 603 }
551 604
552 return success; 605 return success;
553 } 606 }
554 607
555 608
556 bool HttpClient::Apply(std::string& answer) 609 bool HttpClient::ApplyInternal(Json::Value& answer,
557 { 610 HttpClient::HttpHeaders* answerHeaders)
558 return ApplyInternal(answer);
559 }
560
561
562 bool HttpClient::Apply(Json::Value& answer)
563 { 611 {
564 std::string s; 612 std::string s;
565 if (Apply(s)) 613 if (ApplyInternal(s, answerHeaders))
566 { 614 {
567 Json::Reader reader; 615 Json::Reader reader;
568 return reader.parse(s, answer); 616 return reader.parse(s, answer);
569 } 617 }
570 else 618 else