changeset 2041:9f61ca1e3eb3

OrthancPluginHttpClient can return the HTTP headers of the answer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 21 Jun 2016 17:08:09 +0200
parents 6ea2e264ca50
children 5b93382f88e1
files Core/HttpClient.cpp Core/HttpClient.h Plugins/Engine/OrthancPlugins.cpp Plugins/Include/orthanc/OrthancCPlugin.h
diffstat 4 files changed, 92 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpClient.cpp	Tue Jun 21 16:34:30 2016 +0200
+++ b/Core/HttpClient.cpp	Tue Jun 21 17:08:09 2016 +0200
@@ -388,13 +388,13 @@
   }
 
 
-  bool HttpClient::ApplyInternal(std::string& answer,
-                                 HttpHeaders* headers)
+  bool HttpClient::ApplyInternal(std::string& answerBody,
+                                 HttpHeaders* answerHeaders)
   {
-    answer.clear();
+    answerBody.clear();
     CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str()));
 
-    if (headers == NULL)
+    if (answerHeaders == NULL)
     {
       CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, NULL));
       CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, NULL));
@@ -402,7 +402,7 @@
     else
     {
       CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERFUNCTION, &CurlHeaderCallback));
-      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, headers));
+      CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADERDATA, answerHeaders));
     }
 
 #if ORTHANC_SSL_ENABLED == 1
@@ -593,11 +593,11 @@
 
     if (success)
     {
-      buffer.Flatten(answer);
+      buffer.Flatten(answerBody);
     }
     else
     {
-      answer.clear();
+      answerBody.clear();
       LOG(INFO) << "Error in HTTP request, received HTTP status " << status 
                 << " (" << EnumerationToString(lastStatus_) << ")";
     }
@@ -606,14 +606,14 @@
   }
 
 
-  bool HttpClient::ApplyInternal(Json::Value& answer,
+  bool HttpClient::ApplyInternal(Json::Value& answerBody,
                                  HttpClient::HttpHeaders* answerHeaders)
   {
     std::string s;
     if (ApplyInternal(s, answerHeaders))
     {
       Json::Reader reader;
-      return reader.parse(s, answer);
+      return reader.parse(s, answerBody);
     }
     else
     {
@@ -689,17 +689,38 @@
   }
 
 
-  void HttpClient::ApplyAndThrowException(std::string& answer)
+  void HttpClient::ApplyAndThrowException(std::string& answerBody)
+  {
+    if (!Apply(answerBody))
+    {
+      ThrowException(GetLastStatus());
+    }
+  }
+
+  
+  void HttpClient::ApplyAndThrowException(Json::Value& answerBody)
   {
-    if (!Apply(answer))
+    if (!Apply(answerBody))
+    {
+      ThrowException(GetLastStatus());
+    }
+  }
+
+
+  void HttpClient::ApplyAndThrowException(std::string& answerBody,
+                                          HttpHeaders& answerHeaders)
+  {
+    if (!Apply(answerBody, answerHeaders))
     {
       ThrowException(GetLastStatus());
     }
   }
   
-  void HttpClient::ApplyAndThrowException(Json::Value& answer)
+
+  void HttpClient::ApplyAndThrowException(Json::Value& answerBody,
+                                          HttpHeaders& answerHeaders)
   {
-    if (!Apply(answer))
+    if (!Apply(answerBody, answerHeaders))
     {
       ThrowException(GetLastStatus());
     }
--- a/Core/HttpClient.h	Tue Jun 21 16:34:30 2016 +0200
+++ b/Core/HttpClient.h	Tue Jun 21 17:08:09 2016 +0200
@@ -72,10 +72,10 @@
     void operator= (const HttpClient&);  // Assignment forbidden
     HttpClient(const HttpClient& base);  // Copy forbidden
 
-    bool ApplyInternal(std::string& answer,
+    bool ApplyInternal(std::string& answerBody,
                        HttpHeaders* answerHeaders);
 
-    bool ApplyInternal(Json::Value& answer,
+    bool ApplyInternal(Json::Value& answerBody,
                        HttpHeaders* answerHeaders);
 
   public:
@@ -148,26 +148,26 @@
 
     void ClearHeaders();
 
-    bool Apply(std::string& answer)
+    bool Apply(std::string& answerBody)
     {
-      return ApplyInternal(answer, NULL);
+      return ApplyInternal(answerBody, NULL);
     }
 
-    bool Apply(Json::Value& answer)
+    bool Apply(Json::Value& answerBody)
     {
-      return ApplyInternal(answer, NULL);
+      return ApplyInternal(answerBody, NULL);
     }
 
-    bool Apply(std::string& answer,
+    bool Apply(std::string& answerBody,
                HttpHeaders& answerHeaders)
     {
-      return ApplyInternal(answer, &answerHeaders);
+      return ApplyInternal(answerBody, &answerHeaders);
     }
 
-    bool Apply(Json::Value& answer,
+    bool Apply(Json::Value& answerBody,
                HttpHeaders& answerHeaders)
     {
-      return ApplyInternal(answer, &answerHeaders);
+      return ApplyInternal(answerBody, &answerHeaders);
     }
 
     HttpStatus GetLastStatus() const
@@ -247,8 +247,14 @@
 
     static void SetDefaultTimeout(long timeout);
 
-    void ApplyAndThrowException(std::string& answer);
+    void ApplyAndThrowException(std::string& answerBody);
+
+    void ApplyAndThrowException(Json::Value& answerBody);
 
-    void ApplyAndThrowException(Json::Value& answer);
+    void ApplyAndThrowException(std::string& answerBody,
+                                HttpHeaders& answerHeaders);
+
+    void ApplyAndThrowException(Json::Value& answerBody,
+                                HttpHeaders& answerHeaders);
   };
 }
--- a/Plugins/Engine/OrthancPlugins.cpp	Tue Jun 21 16:34:30 2016 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Tue Jun 21 17:08:09 2016 +0200
@@ -1811,7 +1811,7 @@
       client.SetClientCertificate(certificate, key, password);
     }
 
-	client.SetPkcs11Enabled(p.pkcs11 ? true : false);
+    client.SetPkcs11Enabled(p.pkcs11 ? true : false);
 
     for (uint32_t i = 0; i < p.headersCount; i++)
     {
@@ -1848,19 +1848,33 @@
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
 
-    std::string s;
-
-    if (!client.Apply(s))
+    std::string body;
+    HttpClient::HttpHeaders headers;
+
+    client.ApplyAndThrowException(body, headers);
+
+    // The HTTP request has succeeded
+    *p.httpStatus = static_cast<uint16_t>(client.GetLastStatus());
+
+    // Copy the HTTP headers of the answer, if the plugin requested them
+    if (p.answerHeaders != NULL)
     {
-      *p.httpStatus = 0;
-      throw OrthancException(ErrorCode_NetworkProtocol);
+      Json::Value json = Json::objectValue;
+
+      for (HttpClient::HttpHeaders::const_iterator 
+             it = headers.begin(); it != headers.end(); ++it)
+      {
+        json[it->first] = it->second;
+      }
+        
+      std::string s = json.toStyledString();
+      CopyToMemoryBuffer(*p.answerHeaders, s);
     }
 
-    *p.httpStatus = static_cast<uint16_t>(client.GetLastStatus());
-
+    // Copy the body of the answer if it makes sense
     if (p.method != OrthancPluginHttpMethod_Delete)
     {
-      CopyToMemoryBuffer(*p.target, s);
+      CopyToMemoryBuffer(*p.answerBody, body);
     }
   }
 
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Jun 21 16:34:30 2016 +0200
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Jun 21 17:08:09 2016 +0200
@@ -4931,7 +4931,8 @@
 
   typedef struct
   {
-    OrthancPluginMemoryBuffer*  target;
+    OrthancPluginMemoryBuffer*  answerBody;
+    OrthancPluginMemoryBuffer*  answerHeaders;
     uint16_t*                   httpStatus;
     OrthancPluginHttpMethod     method;
     const char*                 url;
@@ -4955,10 +4956,19 @@
    * @brief Issue a HTTP call with full flexibility.
    * 
    * Make a HTTP call to the given URL. The result to the query is
-   * stored into a newly allocated memory buffer.
+   * stored into a newly allocated memory buffer. The HTTP request
+   * will be done accordingly to the global configuration of Orthanc
+   * (in particular, the options "HttpProxy", "HttpTimeout",
+   * "HttpsVerifyPeers", "HttpsCACertificates", and "Pkcs11" will be
+   * taken into account).
    * 
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
-   * @param target The target memory buffer. It must be freed with OrthancPluginFreeMemoryBuffer() (out argument).
+   * @param answerBody The target memory buffer (out argument).
+   *        It must be freed with OrthancPluginFreeMemoryBuffer().
+   * @param answerHeaders The target memory buffer for the HTTP headers in the answers (out argument). 
+   *        The answer headers are formatted as a JSON object (associative array).
+   *        The buffer must be freed with OrthancPluginFreeMemoryBuffer().
+   *        This argument can be set to NULL if the plugin has no interest in the HTTP headers.
    * @param httpStatus The HTTP status after the execution of the request (out argument).
    * @param method HTTP method to be used.
    * @param url The URL of interest.
@@ -4981,7 +4991,8 @@
    **/
   ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode  OrthancPluginHttpClient(
     OrthancPluginContext*       context,
-    OrthancPluginMemoryBuffer*  target,
+    OrthancPluginMemoryBuffer*  answerBody,
+    OrthancPluginMemoryBuffer*  answerHeaders,
     uint16_t*                   httpStatus,
     OrthancPluginHttpMethod     method,
     const char*                 url,
@@ -5001,7 +5012,8 @@
     _OrthancPluginCallHttpClient2 params;
     memset(&params, 0, sizeof(params));
 
-    params.target = target;
+    params.answerBody = answerBody;
+    params.answerHeaders = answerHeaders;
     params.httpStatus = httpStatus;
     params.method = method;
     params.url = url;