diff 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
line wrap: on
line diff
--- a/Core/HttpClient.cpp	Mon Apr 25 17:23:07 2016 +0200
+++ b/Core/HttpClient.cpp	Tue Apr 26 17:40:55 2016 +0200
@@ -42,10 +42,6 @@
 #include <boost/algorithm/string/predicate.hpp>
 
 
-static std::string globalCACertificates_;
-static bool globalVerifyPeers_ = true;
-static long globalTimeout_ = 0;
-
 extern "C"
 {
   static CURLcode GetHttpStatus(CURLcode code, CURL* curl, long* status)
@@ -77,6 +73,79 @@
 
 namespace Orthanc
 {
+  class HttpClient::GlobalParameters
+  {
+  private:
+    boost::mutex    mutex_;
+    bool            httpsVerifyPeers_;
+    std::string     httpsCACertificates_;
+    std::string     proxy_;
+    long            timeout_;
+
+    GlobalParameters() : 
+      httpsVerifyPeers_(true),
+      timeout_(0)
+    {
+    }
+
+  public:
+    // Singleton pattern
+    static GlobalParameters& GetInstance()
+    {
+      static GlobalParameters parameters;
+      return parameters;
+    }
+
+    void ConfigureSsl(bool httpsVerifyPeers,
+                      const std::string& httpsCACertificates)
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+      httpsVerifyPeers_ = httpsVerifyPeers;
+      httpsCACertificates_ = httpsCACertificates;
+    }
+
+    void GetSslConfiguration(bool& httpsVerifyPeers,
+                             std::string& httpsCACertificates)
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+      httpsVerifyPeers = httpsVerifyPeers_;
+      httpsCACertificates = httpsCACertificates_;
+    }
+
+    void SetDefaultProxy(const std::string& proxy)
+    {
+      LOG(INFO) << "Setting the default proxy for HTTP client connections: " << proxy;
+
+      {
+        boost::mutex::scoped_lock lock(mutex_);
+        proxy_ = proxy;
+      }
+    }
+
+    void GetDefaultProxy(std::string& target)
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+      target = proxy_;
+    }
+
+    void SetDefaultTimeout(long seconds)
+    {
+      LOG(INFO) << "Setting the default timeout for HTTP client connections: " << seconds << " seconds";
+
+      {
+        boost::mutex::scoped_lock lock(mutex_);
+        timeout_ = seconds;
+      }
+    }
+
+    long GetDefaultTimeout()
+    {
+      boost::mutex::scoped_lock lock(mutex_);
+      return timeout_;
+    }
+  };
+
+
   struct HttpClient::PImpl
   {
     CURL* curl_;
@@ -93,6 +162,7 @@
         throw OrthancException(ErrorCode_BadRequest);
 
       case HttpStatus_401_Unauthorized:
+      case HttpStatus_403_Forbidden:
         throw OrthancException(ErrorCode_Unauthorized);
 
       case HttpStatus_404_NotFound:
@@ -163,8 +233,9 @@
     method_ = HttpMethod_Get;
     lastStatus_ = HttpStatus_200_Ok;
     isVerbose_ = false;
-    timeout_ = globalTimeout_;
-    verifyPeers_ = globalVerifyPeers_;
+    timeout_ = GlobalParameters::GetInstance().GetDefaultTimeout();
+    GlobalParameters::GetInstance().GetDefaultProxy(proxy_);
+    GlobalParameters::GetInstance().GetSslConfiguration(verifyPeers_, caCertificates_);
   }
 
 
@@ -174,22 +245,6 @@
   }
 
 
-  HttpClient::HttpClient(const HttpClient& other) : pimpl_(new PImpl)
-  {
-    Setup();
-
-    if (other.IsVerbose())
-    {
-      SetVerbose(true);
-    }
-
-    if (other.credentials_.size() != 0)
-    {
-      credentials_ = other.credentials_;
-    }
-  }
-
-
   HttpClient::~HttpClient()
   {
     curl_easy_cleanup(pimpl_->curl_);
@@ -248,9 +303,9 @@
 
     // Setup HTTPS-related options
 #if ORTHANC_SSL_ENABLED == 1
-    if (IsHttpsVerifyPeers())
+    if (verifyPeers_)
     {
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CAINFO, GetHttpsCACertificates().c_str()));
+      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CAINFO, caCertificates_.c_str()));
       CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYHOST, 2));  // libcurl default is strict verifyhost
       CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_SSL_VERIFYPEER, 1)); 
     }
@@ -375,7 +430,15 @@
       lastStatus_ = static_cast<HttpStatus>(status);
     }
 
-    return (status >= 200 && status < 300);
+    bool success = (status >= 200 && status < 300);
+
+    if (!success)
+    {
+      LOG(INFO) << "Error in HTTP request, received HTTP status " << status 
+                << " (" << EnumerationToString(lastStatus_) << ")";
+    }
+
+    return success;
   }
 
 
@@ -400,59 +463,54 @@
     credentials_ = std::string(username) + ":" + std::string(password);
   }
 
-  
-  const std::string& HttpClient::GetHttpsCACertificates() const
+
+  void HttpClient::ConfigureSsl(bool httpsVerifyPeers,
+                                const std::string& httpsVerifyCertificates)
   {
-    if (caCertificates_.empty())
-    {
-      return globalCACertificates_;
-    }
-    else
-    {
-      return caCertificates_;
-    }
-  }
-
-
-  void HttpClient::GlobalInitialize(bool httpsVerifyPeers,
-                                    const std::string& httpsVerifyCertificates)
-  {
-    globalVerifyPeers_ = httpsVerifyPeers;
-    globalCACertificates_ = httpsVerifyCertificates;
-
 #if ORTHANC_SSL_ENABLED == 1
     if (httpsVerifyPeers)
     {
-      if (globalCACertificates_.empty())
+      if (httpsVerifyCertificates.empty())
       {
         LOG(WARNING) << "No certificates are provided to validate peers, "
                      << "set \"HttpsCACertificates\" if you need to do HTTPS requests";
       }
       else
       {
-        LOG(WARNING) << "HTTPS will use the CA certificates from this file: " << globalCACertificates_;
+        LOG(WARNING) << "HTTPS will use the CA certificates from this file: " << httpsVerifyCertificates;
       }
     }
     else
     {
-      LOG(WARNING) << "The verification of the peers in HTTPS requests is disabled!";
+      LOG(WARNING) << "The verification of the peers in HTTPS requests is disabled";
     }
 #endif
 
+    GlobalParameters::GetInstance().ConfigureSsl(httpsVerifyPeers, httpsVerifyCertificates);
+  }
+
+  
+  void HttpClient::GlobalInitialize()
+  {
     CheckCode(curl_global_init(CURL_GLOBAL_DEFAULT));
   }
 
-  
+
   void HttpClient::GlobalFinalize()
   {
     curl_global_cleanup();
   }
+  
 
-  
+  void HttpClient::SetDefaultProxy(const std::string& proxy)
+  {
+    GlobalParameters::GetInstance().SetDefaultProxy(proxy);
+  }
+
+
   void HttpClient::SetDefaultTimeout(long timeout)
   {
-    LOG(INFO) << "Setting the default timeout for HTTP client connections: " << timeout << " seconds";
-    globalTimeout_ = timeout;
+    GlobalParameters::GetInstance().SetDefaultTimeout(timeout);
   }