Mercurial > hg > orthanc
comparison Core/HttpClient.cpp @ 1987:ce90d109bb64
new plugin functions: OrthancPluginHttpClient and OrthancPluginGenerateUuid
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 26 Apr 2016 17:40:55 +0200 |
parents | 99b249867052 |
children | f3339c4f8bf4 |
comparison
equal
deleted
inserted
replaced
1986:99b249867052 | 1987:ce90d109bb64 |
---|---|
40 #include <string.h> | 40 #include <string.h> |
41 #include <curl/curl.h> | 41 #include <curl/curl.h> |
42 #include <boost/algorithm/string/predicate.hpp> | 42 #include <boost/algorithm/string/predicate.hpp> |
43 | 43 |
44 | 44 |
45 static std::string globalCACertificates_; | |
46 static bool globalVerifyPeers_ = true; | |
47 static long globalTimeout_ = 0; | |
48 | |
49 extern "C" | 45 extern "C" |
50 { | 46 { |
51 static CURLcode GetHttpStatus(CURLcode code, CURL* curl, long* status) | 47 static CURLcode GetHttpStatus(CURLcode code, CURL* curl, long* status) |
52 { | 48 { |
53 if (code == CURLE_OK) | 49 if (code == CURLE_OK) |
75 | 71 |
76 | 72 |
77 | 73 |
78 namespace Orthanc | 74 namespace Orthanc |
79 { | 75 { |
76 class HttpClient::GlobalParameters | |
77 { | |
78 private: | |
79 boost::mutex mutex_; | |
80 bool httpsVerifyPeers_; | |
81 std::string httpsCACertificates_; | |
82 std::string proxy_; | |
83 long timeout_; | |
84 | |
85 GlobalParameters() : | |
86 httpsVerifyPeers_(true), | |
87 timeout_(0) | |
88 { | |
89 } | |
90 | |
91 public: | |
92 // Singleton pattern | |
93 static GlobalParameters& GetInstance() | |
94 { | |
95 static GlobalParameters parameters; | |
96 return parameters; | |
97 } | |
98 | |
99 void ConfigureSsl(bool httpsVerifyPeers, | |
100 const std::string& httpsCACertificates) | |
101 { | |
102 boost::mutex::scoped_lock lock(mutex_); | |
103 httpsVerifyPeers_ = httpsVerifyPeers; | |
104 httpsCACertificates_ = httpsCACertificates; | |
105 } | |
106 | |
107 void GetSslConfiguration(bool& httpsVerifyPeers, | |
108 std::string& httpsCACertificates) | |
109 { | |
110 boost::mutex::scoped_lock lock(mutex_); | |
111 httpsVerifyPeers = httpsVerifyPeers_; | |
112 httpsCACertificates = httpsCACertificates_; | |
113 } | |
114 | |
115 void SetDefaultProxy(const std::string& proxy) | |
116 { | |
117 LOG(INFO) << "Setting the default proxy for HTTP client connections: " << proxy; | |
118 | |
119 { | |
120 boost::mutex::scoped_lock lock(mutex_); | |
121 proxy_ = proxy; | |
122 } | |
123 } | |
124 | |
125 void GetDefaultProxy(std::string& target) | |
126 { | |
127 boost::mutex::scoped_lock lock(mutex_); | |
128 target = proxy_; | |
129 } | |
130 | |
131 void SetDefaultTimeout(long seconds) | |
132 { | |
133 LOG(INFO) << "Setting the default timeout for HTTP client connections: " << seconds << " seconds"; | |
134 | |
135 { | |
136 boost::mutex::scoped_lock lock(mutex_); | |
137 timeout_ = seconds; | |
138 } | |
139 } | |
140 | |
141 long GetDefaultTimeout() | |
142 { | |
143 boost::mutex::scoped_lock lock(mutex_); | |
144 return timeout_; | |
145 } | |
146 }; | |
147 | |
148 | |
80 struct HttpClient::PImpl | 149 struct HttpClient::PImpl |
81 { | 150 { |
82 CURL* curl_; | 151 CURL* curl_; |
83 struct curl_slist *defaultPostHeaders_; | 152 struct curl_slist *defaultPostHeaders_; |
84 struct curl_slist *userHeaders_; | 153 struct curl_slist *userHeaders_; |
91 { | 160 { |
92 case HttpStatus_400_BadRequest: | 161 case HttpStatus_400_BadRequest: |
93 throw OrthancException(ErrorCode_BadRequest); | 162 throw OrthancException(ErrorCode_BadRequest); |
94 | 163 |
95 case HttpStatus_401_Unauthorized: | 164 case HttpStatus_401_Unauthorized: |
165 case HttpStatus_403_Forbidden: | |
96 throw OrthancException(ErrorCode_Unauthorized); | 166 throw OrthancException(ErrorCode_Unauthorized); |
97 | 167 |
98 case HttpStatus_404_NotFound: | 168 case HttpStatus_404_NotFound: |
99 throw OrthancException(ErrorCode_InexistentItem); | 169 throw OrthancException(ErrorCode_InexistentItem); |
100 | 170 |
161 | 231 |
162 url_ = ""; | 232 url_ = ""; |
163 method_ = HttpMethod_Get; | 233 method_ = HttpMethod_Get; |
164 lastStatus_ = HttpStatus_200_Ok; | 234 lastStatus_ = HttpStatus_200_Ok; |
165 isVerbose_ = false; | 235 isVerbose_ = false; |
166 timeout_ = globalTimeout_; | 236 timeout_ = GlobalParameters::GetInstance().GetDefaultTimeout(); |
167 verifyPeers_ = globalVerifyPeers_; | 237 GlobalParameters::GetInstance().GetDefaultProxy(proxy_); |
238 GlobalParameters::GetInstance().GetSslConfiguration(verifyPeers_, caCertificates_); | |
168 } | 239 } |
169 | 240 |
170 | 241 |
171 HttpClient::HttpClient() : pimpl_(new PImpl) | 242 HttpClient::HttpClient() : pimpl_(new PImpl) |
172 { | 243 { |
173 Setup(); | 244 Setup(); |
174 } | |
175 | |
176 | |
177 HttpClient::HttpClient(const HttpClient& other) : pimpl_(new PImpl) | |
178 { | |
179 Setup(); | |
180 | |
181 if (other.IsVerbose()) | |
182 { | |
183 SetVerbose(true); | |
184 } | |
185 | |
186 if (other.credentials_.size() != 0) | |
187 { | |
188 credentials_ = other.credentials_; | |
189 } | |
190 } | 245 } |
191 | 246 |
192 | 247 |
193 HttpClient::~HttpClient() | 248 HttpClient::~HttpClient() |
194 { | 249 { |
246 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); | 301 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); |
247 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); | 302 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); |
248 | 303 |
249 // Setup HTTPS-related options | 304 // Setup HTTPS-related options |
250 #if ORTHANC_SSL_ENABLED == 1 | 305 #if ORTHANC_SSL_ENABLED == 1 |
251 if (IsHttpsVerifyPeers()) | 306 if (verifyPeers_) |
252 { | 307 { |
253 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CAINFO, GetHttpsCACertificates().c_str())); | 308 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CAINFO, caCertificates_.c_str())); |
254 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYHOST, 2)); // libcurl default is strict verifyhost | 309 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYHOST, 2)); // libcurl default is strict verifyhost |
255 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 1)); | 310 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 1)); |
256 } | 311 } |
257 else | 312 else |
258 { | 313 { |
373 else | 428 else |
374 { | 429 { |
375 lastStatus_ = static_cast<HttpStatus>(status); | 430 lastStatus_ = static_cast<HttpStatus>(status); |
376 } | 431 } |
377 | 432 |
378 return (status >= 200 && status < 300); | 433 bool success = (status >= 200 && status < 300); |
434 | |
435 if (!success) | |
436 { | |
437 LOG(INFO) << "Error in HTTP request, received HTTP status " << status | |
438 << " (" << EnumerationToString(lastStatus_) << ")"; | |
439 } | |
440 | |
441 return success; | |
379 } | 442 } |
380 | 443 |
381 | 444 |
382 bool HttpClient::Apply(Json::Value& answer) | 445 bool HttpClient::Apply(Json::Value& answer) |
383 { | 446 { |
398 const char* password) | 461 const char* password) |
399 { | 462 { |
400 credentials_ = std::string(username) + ":" + std::string(password); | 463 credentials_ = std::string(username) + ":" + std::string(password); |
401 } | 464 } |
402 | 465 |
403 | 466 |
404 const std::string& HttpClient::GetHttpsCACertificates() const | 467 void HttpClient::ConfigureSsl(bool httpsVerifyPeers, |
405 { | 468 const std::string& httpsVerifyCertificates) |
406 if (caCertificates_.empty()) | 469 { |
407 { | |
408 return globalCACertificates_; | |
409 } | |
410 else | |
411 { | |
412 return caCertificates_; | |
413 } | |
414 } | |
415 | |
416 | |
417 void HttpClient::GlobalInitialize(bool httpsVerifyPeers, | |
418 const std::string& httpsVerifyCertificates) | |
419 { | |
420 globalVerifyPeers_ = httpsVerifyPeers; | |
421 globalCACertificates_ = httpsVerifyCertificates; | |
422 | |
423 #if ORTHANC_SSL_ENABLED == 1 | 470 #if ORTHANC_SSL_ENABLED == 1 |
424 if (httpsVerifyPeers) | 471 if (httpsVerifyPeers) |
425 { | 472 { |
426 if (globalCACertificates_.empty()) | 473 if (httpsVerifyCertificates.empty()) |
427 { | 474 { |
428 LOG(WARNING) << "No certificates are provided to validate peers, " | 475 LOG(WARNING) << "No certificates are provided to validate peers, " |
429 << "set \"HttpsCACertificates\" if you need to do HTTPS requests"; | 476 << "set \"HttpsCACertificates\" if you need to do HTTPS requests"; |
430 } | 477 } |
431 else | 478 else |
432 { | 479 { |
433 LOG(WARNING) << "HTTPS will use the CA certificates from this file: " << globalCACertificates_; | 480 LOG(WARNING) << "HTTPS will use the CA certificates from this file: " << httpsVerifyCertificates; |
434 } | 481 } |
435 } | 482 } |
436 else | 483 else |
437 { | 484 { |
438 LOG(WARNING) << "The verification of the peers in HTTPS requests is disabled!"; | 485 LOG(WARNING) << "The verification of the peers in HTTPS requests is disabled"; |
439 } | 486 } |
440 #endif | 487 #endif |
441 | 488 |
489 GlobalParameters::GetInstance().ConfigureSsl(httpsVerifyPeers, httpsVerifyCertificates); | |
490 } | |
491 | |
492 | |
493 void HttpClient::GlobalInitialize() | |
494 { | |
442 CheckCode(curl_global_init(CURL_GLOBAL_DEFAULT)); | 495 CheckCode(curl_global_init(CURL_GLOBAL_DEFAULT)); |
443 } | 496 } |
444 | 497 |
498 | |
499 void HttpClient::GlobalFinalize() | |
500 { | |
501 curl_global_cleanup(); | |
502 } | |
445 | 503 |
446 void HttpClient::GlobalFinalize() | 504 |
447 { | 505 void HttpClient::SetDefaultProxy(const std::string& proxy) |
448 curl_global_cleanup(); | 506 { |
449 } | 507 GlobalParameters::GetInstance().SetDefaultProxy(proxy); |
450 | 508 } |
451 | 509 |
510 | |
452 void HttpClient::SetDefaultTimeout(long timeout) | 511 void HttpClient::SetDefaultTimeout(long timeout) |
453 { | 512 { |
454 LOG(INFO) << "Setting the default timeout for HTTP client connections: " << timeout << " seconds"; | 513 GlobalParameters::GetInstance().SetDefaultTimeout(timeout); |
455 globalTimeout_ = timeout; | |
456 } | 514 } |
457 | 515 |
458 | 516 |
459 void HttpClient::ApplyAndThrowException(std::string& answer) | 517 void HttpClient::ApplyAndThrowException(std::string& answer) |
460 { | 518 { |