changeset 44:f4e828607f02

Added 'SenderTransferID' option that is added as an HTTP header in outgoing requests in PushMode
author Alain Mazy <am@osimis.io>
date Wed, 19 Oct 2022 21:12:57 +0200
parents c3fefbb11321
children f633b835c5bd
files Framework/HttpQueries/DetectTransferPlugin.h Framework/HttpQueries/HttpQueriesQueue.cpp Framework/HttpQueries/IHttpQuery.h Framework/PullMode/BucketPullQuery.h Framework/PullMode/PullJob.cpp Framework/PushMode/BucketPushQuery.cpp Framework/PushMode/BucketPushQuery.h Framework/PushMode/PushJob.cpp Framework/TransferQuery.cpp Framework/TransferQuery.h Framework/TransferToolbox.cpp Framework/TransferToolbox.h NEWS Plugin/Plugin.cpp Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h
diffstat 16 files changed, 180 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/HttpQueries/DetectTransferPlugin.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/HttpQueries/DetectTransferPlugin.h	Wed Oct 19 21:12:57 2022 +0200
@@ -61,6 +61,9 @@
     virtual void HandleAnswer(const void* answer,
                               size_t size);
 
+    virtual void GetHttpHeaders(std::map<std::string, std::string>& headers) const
+    {/* no headers for this general purpose request*/}
+
     static void Apply(Result& result,
                       size_t threadsCount,
                       unsigned int timeout);
--- a/Framework/HttpQueries/HttpQueriesQueue.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/HttpQueries/HttpQueriesQueue.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -135,6 +135,9 @@
     {
       query->ReadBody(body);              
     }       
+    
+    std::map<std::string, std::string> headers;
+    query->GetHttpHeaders(headers);
 
     unsigned int retry = 0;
 
@@ -149,19 +152,19 @@
         switch (query->GetMethod())
         {
           case Orthanc::HttpMethod_Get:
-            success = peers_.DoGet(answer, query->GetPeer(), query->GetUri());
+            success = peers_.DoGet(answer, query->GetPeer(), query->GetUri(), headers);
             break;
 
           case Orthanc::HttpMethod_Post:
-            success = peers_.DoPost(answer, query->GetPeer(), query->GetUri(), body);
+            success = peers_.DoPost(answer, query->GetPeer(), query->GetUri(), body, headers);
             break;
 
           case Orthanc::HttpMethod_Put:
-            success = peers_.DoPut(query->GetPeer(), query->GetUri(), body);
+            success = peers_.DoPut(query->GetPeer(), query->GetUri(), body, headers);
             break;
 
           case Orthanc::HttpMethod_Delete:
-            success = peers_.DoDelete(query->GetPeer(), query->GetUri());
+            success = peers_.DoDelete(query->GetPeer(), query->GetUri(), headers);
             break;
 
           default:
@@ -171,7 +174,7 @@
       catch (Orthanc::OrthancException& e)
       {
         LOG(ERROR) << "Unhandled exception during an HTTP query to peer \"" 
-                   << query->GetPeer() << "\": " << e.What();
+                   << query->GetPeer() <<  " " << query->GetUri() + "\": " << e.What();
         success = false;
       }
 
@@ -221,7 +224,10 @@
         }
         else
         {
-          LOG(INFO) << "Reached the maximum number of retries for a HTTP query";
+          if (maxRetries > 0)
+          {
+            LOG(ERROR) << "Reached the maximum number of retries for a HTTP query to peer " << query->GetPeer() <<  " " << query->GetUri();
+          }
 
           {
             boost::mutex::scoped_lock lock(mutex_);
--- a/Framework/HttpQueries/IHttpQuery.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/HttpQueries/IHttpQuery.h	Wed Oct 19 21:12:57 2022 +0200
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <Enumerations.h>
+#include <map>
 
 #include <boost/noncopyable.hpp>
 
@@ -43,5 +44,7 @@
 
     virtual void HandleAnswer(const void* answer,
                               size_t size) = 0;
+
+    virtual void GetHttpHeaders(std::map<std::string, std::string>& headers) const = 0;
   };
 }
--- a/Framework/PullMode/BucketPullQuery.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/PullMode/BucketPullQuery.h	Wed Oct 19 21:12:57 2022 +0200
@@ -59,5 +59,8 @@
 
     virtual void HandleAnswer(const void* answer,
                               size_t size);
+    
+    virtual void GetHttpHeaders(std::map<std::string, std::string>& headers) const
+    {}
   };
 }
--- a/Framework/PullMode/PullJob.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/PullMode/PullJob.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -176,7 +176,10 @@
       Orthanc::Toolbox::WriteFastJson(lookup, job_.query_.GetResources());
 
       Json::Value answer;
-      if (!DoPostPeer(answer, job_.peers_, job_.peerIndex_, URI_LOOKUP, lookup, job_.maxHttpRetries_))
+      std::map<std::string, std::string> headers;
+      job_.query_.GetHttpHeaders(headers);
+
+      if (!DoPostPeer(answer, job_.peers_, job_.peerIndex_, URI_LOOKUP, lookup, job_.maxHttpRetries_, headers))
       {
         LOG(ERROR) << "Cannot retrieve the list of instances to pull from peer \"" 
                    << job_.query_.GetPeer()
--- a/Framework/PushMode/BucketPushQuery.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/PushMode/BucketPushQuery.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -32,12 +32,14 @@
                                    const std::string& peer,
                                    const std::string& transactionUri,
                                    size_t bucketIndex,
-                                   BucketCompression compression) :
+                                   BucketCompression compression,
+                                   const std::map<std::string, std::string>& headers) :
     cache_(cache),
     bucket_(bucket),
     peer_(peer),
     uri_(transactionUri + "/" + boost::lexical_cast<std::string>(bucketIndex)),
-    compression_(compression)
+    compression_(compression),
+    headers_(headers)
   {
   }
 
--- a/Framework/PushMode/BucketPushQuery.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/PushMode/BucketPushQuery.h	Wed Oct 19 21:12:57 2022 +0200
@@ -32,6 +32,7 @@
     std::string             peer_;
     std::string             uri_;
     BucketCompression       compression_;
+    std::map<std::string, std::string> headers_;
 
   public:
     BucketPushQuery(OrthancInstancesCache& cache,
@@ -39,7 +40,8 @@
                     const std::string& peer,
                     const std::string& transactionUri,
                     size_t bucketIndex,
-                    BucketCompression compression);
+                    BucketCompression compression,
+                    const std::map<std::string, std::string>& headers);
 
     virtual Orthanc::HttpMethod GetMethod() const
     {
@@ -60,5 +62,10 @@
 
     virtual void HandleAnswer(const void* answer,
                               size_t size);
+
+    virtual void GetHttpHeaders(std::map<std::string, std::string>& headers) const
+    {
+      headers = headers_;
+    }
   };
 }
--- a/Framework/PushMode/PushJob.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/PushMode/PushJob.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -53,21 +53,23 @@
     {
       Json::Value answer;
       bool success = false;
+      std::map<std::string, std::string> headers;
+      job_.query_.GetHttpHeaders(headers);
 
       if (isCommit_)
       {
-        success = DoPostPeer(answer, job_.peers_, job_.peerIndex_, transactionUri_ + "/commit", "", job_.maxHttpRetries_);
+        success = DoPostPeer(answer, job_.peers_, job_.peerIndex_, transactionUri_ + "/commit", "", job_.maxHttpRetries_, headers);
       }
       else
       {
-        success = DoDeletePeer(job_.peers_, job_.peerIndex_, transactionUri_, job_.maxHttpRetries_);
+        success = DoDeletePeer(job_.peers_, job_.peerIndex_, transactionUri_, job_.maxHttpRetries_, headers);
       }
         
       if (!success)
       {
         if (isCommit_)
         {
-          LOG(ERROR) << "Cannot commit push transaction on remote peer: "
+          LOG(ERROR) << "Cannot commit push transaction on remote peer: " // TODO: add job ID
                      << job_.query_.GetPeer();
         }
           
@@ -129,13 +131,16 @@
       info_(info),
       transactionUri_(transactionUri)
     {
+      std::map<std::string, std::string> headers;
+      job_.query_.GetHttpHeaders(headers);
+
       queue_.SetMaxRetries(job.maxHttpRetries_);
       queue_.Reserve(buckets.size());
         
       for (size_t i = 0; i < buckets.size(); i++)
       {
         queue_.Enqueue(new BucketPushQuery(job.cache_, buckets[i], job.query_.GetPeer(),
-                                           transactionUri_, i, job.query_.GetCompression()));
+                                           transactionUri_, i, job.query_.GetCompression(), headers));
       }
 
       UpdateInfo();
@@ -212,7 +217,10 @@
     virtual StateUpdate* Step()
     {
       Json::Value answer;
-      if (!DoPostPeer(answer, job_.peers_, job_.peerIndex_, URI_PUSH, createTransaction_, job_.maxHttpRetries_))
+      std::map<std::string, std::string> headers;
+      job_.query_.GetHttpHeaders(headers);
+
+      if (!DoPostPeer(answer, job_.peers_, job_.peerIndex_, URI_PUSH, createTransaction_, job_.maxHttpRetries_, headers))
       {
         LOG(ERROR) << "Cannot create a push transaction to peer \"" 
                    << job_.query_.GetPeer()
--- a/Framework/TransferQuery.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/TransferQuery.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -20,6 +20,7 @@
 #include "TransferQuery.h"
 
 #include <OrthancException.h>
+#include "Toolbox.h"
 
 
 namespace OrthancPlugins
@@ -74,6 +75,20 @@
     {
       priority_ = 0;
     }
+
+    if (body.isMember(KEY_SENDER_TRANSFER_ID))
+    {
+      if (body[KEY_SENDER_TRANSFER_ID].type() != Json::stringValue)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, std::string(KEY_SENDER_TRANSFER_ID) + " should be a string");
+      }
+      senderTransferId_ = body[KEY_SENDER_TRANSFER_ID].asString();
+    }
+    else
+    {
+      senderTransferId_ = Orthanc::Toolbox::GenerateUuid();
+    }
+    
   }
 
 
@@ -89,6 +104,15 @@
     }
   }
 
+  const std::string& TransferQuery::GetSenderTransferID() const
+  {
+    return senderTransferId_;
+  }
+
+  void TransferQuery::GetHttpHeaders(std::map<std::string, std::string>& headers) const
+  {
+    headers[HEADER_KEY_SENDER_TRANSFER_ID] = senderTransferId_;
+  }
 
   void TransferQuery::Serialize(Json::Value& target) const
   {
@@ -96,7 +120,8 @@
     target[KEY_PEER] = peer_;
     target[KEY_RESOURCES] = resources_;
     target[KEY_COMPRESSION] = EnumerationToString(compression_);
-      
+    target[KEY_SENDER_TRANSFER_ID] = senderTransferId_;
+
     if (hasOriginator_)
     {
       target[KEY_ORIGINATOR_UUID] = originator_;
--- a/Framework/TransferQuery.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/TransferQuery.h	Wed Oct 19 21:12:57 2022 +0200
@@ -34,6 +34,7 @@
     bool               hasOriginator_;
     std::string        originator_;
     int                priority_;
+    std::string        senderTransferId_;
 
   public:
     explicit TransferQuery(const Json::Value& body);
@@ -65,6 +66,10 @@
       return priority_;
     }
 
+    const std::string& GetSenderTransferID() const;
+
+    void GetHttpHeaders(std::map<std::string, std::string>& headers) const;
+
     void Serialize(Json::Value& target) const;
   };
 }
--- a/Framework/TransferToolbox.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/TransferToolbox.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -83,7 +83,9 @@
                   size_t peerIndex,
                   const std::string& uri,
                   const std::string& body,
-                  unsigned int maxRetries)
+                  unsigned int maxRetries,
+                  const std::map<std::string, std::string>& headers
+)
   {
     unsigned int retry = 0;
 
@@ -91,7 +93,7 @@
     {
       try
       {
-        if (peers.DoPost(answer, peerIndex, uri, body))
+        if (peers.DoPost(answer, peerIndex, uri, body, headers))
         {
           return true;
         }
@@ -119,19 +121,21 @@
                   const std::string& peerName,
                   const std::string& uri,
                   const std::string& body,
-                  unsigned int maxRetries)
+                  unsigned int maxRetries,
+                  const std::map<std::string, std::string>& headers)
   {
     size_t index;
 
     return (peers.LookupName(index, peerName) &&
-            DoPostPeer(answer, peers, index, uri, body, maxRetries));
+            DoPostPeer(answer, peers, index, uri, body, maxRetries, headers));
   }
 
 
   bool DoDeletePeer(const OrthancPeers& peers,
                     size_t peerIndex,
                     const std::string& uri,
-                    unsigned int maxRetries)
+                    unsigned int maxRetries,
+                    const std::map<std::string, std::string>& headers)
   {
     unsigned int retry = 0;
 
@@ -139,7 +143,7 @@
     {
       try
       {
-        if (peers.DoDelete(peerIndex, uri))
+        if (peers.DoDelete(peerIndex, uri, headers))
         {
           return true;
         }
--- a/Framework/TransferToolbox.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Framework/TransferToolbox.h	Wed Oct 19 21:12:57 2022 +0200
@@ -47,6 +47,7 @@
 static const char* const KEY_RESOURCES = "Resources";
 static const char* const KEY_SIZE = "Size";
 static const char* const KEY_URL = "URL";
+static const char* const KEY_SENDER_TRANSFER_ID = "SenderTransferID";
 
 static const char* const URI_CHUNKS = "/transfers/chunks";
 static const char* const URI_JOBS = "/jobs";
@@ -57,6 +58,7 @@
 static const char* const URI_PUSH = "/transfers/push";
 static const char* const URI_SEND = "/transfers/send";
 
+static const char* const HEADER_KEY_SENDER_TRANSFER_ID = "sender-transfer-id";
   
 namespace OrthancPlugins
 {
@@ -81,17 +83,20 @@
                   size_t peerIndex,
                   const std::string& uri,
                   const std::string& body,
-                  unsigned int maxRetries);
+                  unsigned int maxRetries,
+                  const std::map<std::string, std::string>& headers);
 
   bool DoPostPeer(Json::Value& answer,
                   const OrthancPeers& peers,
                   const std::string& peerName,
                   const std::string& uri,
                   const std::string& body,
-                  unsigned int maxRetries);
+                  unsigned int maxRetries,
+                  const std::map<std::string, std::string>& headers);
 
   bool DoDeletePeer(const OrthancPeers& peers,
                     size_t peerIndex,
                     const std::string& uri,
-                    unsigned int maxRetries);
+                    unsigned int maxRetries,
+                    const std::map<std::string, std::string>& headers);
 }
--- a/NEWS	Tue Jul 12 17:49:40 2022 +0200
+++ b/NEWS	Wed Oct 19 21:12:57 2022 +0200
@@ -1,3 +1,12 @@
+Pending changes in the mainline
+===============================
+
+* new "SenderTransferID" option when creating a transfer.  This id is added as an HTTP Header
+  ("sender-transfer-id") in every outgoing request that relates to this transfer and can be used 
+  e.g, by a load balancer to route all requests from a single transfer to the same Orthanc.
+  If no "SenderTransferID" is provided, a UUID is generated by the plugin.  This header is only 
+  used in PushMode
+
 Version 1.2 (2022-07-12)
 ========================
 
--- a/Plugin/Plugin.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Plugin/Plugin.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -452,7 +452,10 @@
     Orthanc::Toolbox::WriteFastJson(s, lookup);  
 
     Json::Value answer;
-    if (DoPostPeer(answer, peers, query.GetPeer(), URI_PULL, s, context.GetMaxHttpRetries()) &&
+    std::map<std::string, std::string> headers;
+    query.GetHttpHeaders(headers);
+
+    if (DoPostPeer(answer, peers, query.GetPeer(), URI_PULL, s, context.GetMaxHttpRetries(), headers) &&
         answer.type() == Json::objectValue &&
         answer.isMember(KEY_ID) &&
         answer.isMember(KEY_PATH) &&
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Tue Jul 12 17:49:40 2022 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Wed Oct 19 21:12:57 2022 +0200
@@ -1885,7 +1885,8 @@
 
   bool OrthancPeers::DoGet(MemoryBuffer& target,
                            size_t index,
-                           const std::string& uri) const
+                           const std::string& uri,
+                           const std::map<std::string, std::string>& headers) const
   {
     if (index >= index_.size())
     {
@@ -1894,10 +1895,12 @@
 
     OrthancPlugins::MemoryBuffer answer;
     uint16_t status;
+    PluginHttpHeaders pluginHeaders(headers);
+
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
       (GetGlobalContext(), *answer, NULL, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
+       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
@@ -1913,21 +1916,23 @@
 
   bool OrthancPeers::DoGet(MemoryBuffer& target,
                            const std::string& name,
-                           const std::string& uri) const
+                           const std::string& uri,
+                           const std::map<std::string, std::string>& headers) const
   {
     size_t index;
     return (LookupName(index, name) &&
-            DoGet(target, index, uri));
+            DoGet(target, index, uri, headers));
   }
 
 
   bool OrthancPeers::DoGet(Json::Value& target,
                            size_t index,
-                           const std::string& uri) const
+                           const std::string& uri,
+                           const std::map<std::string, std::string>& headers) const
   {
     MemoryBuffer buffer;
 
-    if (DoGet(buffer, index, uri))
+    if (DoGet(buffer, index, uri, headers))
     {
       buffer.ToJson(target);
       return true;
@@ -1941,11 +1946,12 @@
 
   bool OrthancPeers::DoGet(Json::Value& target,
                            const std::string& name,
-                           const std::string& uri) const
+                           const std::string& uri,
+                           const std::map<std::string, std::string>& headers) const
   {
     MemoryBuffer buffer;
 
-    if (DoGet(buffer, name, uri))
+    if (DoGet(buffer, name, uri, headers))
     {
       buffer.ToJson(target);
       return true;
@@ -1960,22 +1966,24 @@
   bool OrthancPeers::DoPost(MemoryBuffer& target,
                             const std::string& name,
                             const std::string& uri,
-                            const std::string& body) const
+                            const std::string& body,
+                            const std::map<std::string, std::string>& headers) const
   {
     size_t index;
     return (LookupName(index, name) &&
-            DoPost(target, index, uri, body));
+            DoPost(target, index, uri, body, headers));
   }
 
 
   bool OrthancPeers::DoPost(Json::Value& target,
                             size_t index,
                             const std::string& uri,
-                            const std::string& body) const
+                            const std::string& body,
+                            const std::map<std::string, std::string>& headers) const
   {
     MemoryBuffer buffer;
 
-    if (DoPost(buffer, index, uri, body))
+    if (DoPost(buffer, index, uri, body, headers))
     {
       buffer.ToJson(target);
       return true;
@@ -1990,11 +1998,12 @@
   bool OrthancPeers::DoPost(Json::Value& target,
                             const std::string& name,
                             const std::string& uri,
-                            const std::string& body) const
+                            const std::string& body,
+                            const std::map<std::string, std::string>& headers) const
   {
     MemoryBuffer buffer;
 
-    if (DoPost(buffer, name, uri, body))
+    if (DoPost(buffer, name, uri, body, headers))
     {
       buffer.ToJson(target);
       return true;
@@ -2009,7 +2018,8 @@
   bool OrthancPeers::DoPost(MemoryBuffer& target,
                             size_t index,
                             const std::string& uri,
-                            const std::string& body) const
+                            const std::string& body,
+                            const std::map<std::string, std::string>& headers) const
   {
     if (index >= index_.size())
     {
@@ -2024,10 +2034,12 @@
 
     OrthancPlugins::MemoryBuffer answer;
     uint16_t status;
+    PluginHttpHeaders pluginHeaders(headers);
+
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
       (GetGlobalContext(), *answer, NULL, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
+       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
@@ -2043,7 +2055,8 @@
 
   bool OrthancPeers::DoPut(size_t index,
                            const std::string& uri,
-                           const std::string& body) const
+                           const std::string& body,
+                           const std::map<std::string, std::string>& headers) const
   {
     if (index >= index_.size())
     {
@@ -2058,10 +2071,12 @@
 
     OrthancPlugins::MemoryBuffer answer;
     uint16_t status;
+    PluginHttpHeaders pluginHeaders(headers);
+
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
       (GetGlobalContext(), *answer, NULL, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(),
-       0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_);
+       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
@@ -2076,16 +2091,18 @@
 
   bool OrthancPeers::DoPut(const std::string& name,
                            const std::string& uri,
-                           const std::string& body) const
+                           const std::string& body,
+                           const std::map<std::string, std::string>& headers) const
   {
     size_t index;
     return (LookupName(index, name) &&
-            DoPut(index, uri, body));
+            DoPut(index, uri, body, headers));
   }
 
 
   bool OrthancPeers::DoDelete(size_t index,
-                              const std::string& uri) const
+                              const std::string& uri,
+                              const std::map<std::string, std::string>& headers) const
   {
     if (index >= index_.size())
     {
@@ -2094,10 +2111,12 @@
 
     OrthancPlugins::MemoryBuffer answer;
     uint16_t status;
+    PluginHttpHeaders pluginHeaders(headers);
+
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
       (GetGlobalContext(), *answer, NULL, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Delete, uri.c_str(),
-       0, NULL, NULL, NULL, 0, timeout_);
+       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), NULL, 0, timeout_);
 
     if (code == OrthancPluginErrorCode_Success)
     {
@@ -2111,11 +2130,12 @@
 
 
   bool OrthancPeers::DoDelete(const std::string& name,
-                              const std::string& uri) const
+                              const std::string& uri,
+                              const std::map<std::string, std::string>& headers) const
   {
     size_t index;
     return (LookupName(index, name) &&
-            DoDelete(index, uri));
+            DoDelete(index, uri, headers));
   }
 #endif
 
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Tue Jul 12 17:49:40 2022 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Wed Oct 19 21:12:57 2022 +0200
@@ -755,53 +755,65 @@
 
     bool DoGet(MemoryBuffer& target,
                size_t index,
-               const std::string& uri) const;
+               const std::string& uri,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoGet(MemoryBuffer& target,
                const std::string& name,
-               const std::string& uri) const;
+               const std::string& uri,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoGet(Json::Value& target,
                size_t index,
-               const std::string& uri) const;
+               const std::string& uri,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoGet(Json::Value& target,
                const std::string& name,
-               const std::string& uri) const;
+               const std::string& uri,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoPost(MemoryBuffer& target,
                 size_t index,
                 const std::string& uri,
-                const std::string& body) const;
+                const std::string& body,
+                const std::map<std::string, std::string>& headers) const;
 
     bool DoPost(MemoryBuffer& target,
                 const std::string& name,
                 const std::string& uri,
-                const std::string& body) const;
+                const std::string& body,
+                const std::map<std::string, std::string>& headers) const;
 
     bool DoPost(Json::Value& target,
                 size_t index,
                 const std::string& uri,
-                const std::string& body) const;
+                const std::string& body,
+                const std::map<std::string, std::string>& headers) const;
 
     bool DoPost(Json::Value& target,
                 const std::string& name,
                 const std::string& uri,
-                const std::string& body) const;
+                const std::string& body,
+                const std::map<std::string, std::string>& headers) const;
 
     bool DoPut(size_t index,
                const std::string& uri,
-               const std::string& body) const;
+               const std::string& body,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoPut(const std::string& name,
                const std::string& uri,
-               const std::string& body) const;
+               const std::string& body,
+               const std::map<std::string, std::string>& headers) const;
 
     bool DoDelete(size_t index,
-                  const std::string& uri) const;
+                  const std::string& uri,
+                  const std::map<std::string, std::string>& headers) const;
 
     bool DoDelete(const std::string& name,
-                  const std::string& uri) const;
+                  const std::string& uri,
+                  const std::map<std::string, std::string>& headers) const;
   };
 #endif