changeset 1446:8dc80ba768aa

refactoring: IHttpHandler does not use std::string to hold the request body
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 01 Jul 2015 13:16:12 +0200
parents d26c8a93d05a
children 5ba7471780ae
files Core/HttpServer/EmbeddedResourceHttpHandler.cpp Core/HttpServer/EmbeddedResourceHttpHandler.h Core/HttpServer/FilesystemHttpHandler.cpp Core/HttpServer/FilesystemHttpHandler.h Core/HttpServer/HttpToolbox.cpp Core/HttpServer/IHttpHandler.h Core/HttpServer/MongooseServer.cpp Core/RestApi/RestApi.cpp Core/RestApi/RestApi.h Core/RestApi/RestApiPostCall.h Core/RestApi/RestApiPutCall.h Core/Toolbox.cpp Core/Toolbox.h OrthancServer/OrthancHttpHandler.cpp OrthancServer/OrthancHttpHandler.h OrthancServer/OrthancRestApi/OrthancRestApi.cpp OrthancServer/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/OrthancRestApi/OrthancRestResources.cpp OrthancServer/OrthancRestApi/OrthancRestSystem.cpp Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h
diffstat 21 files changed, 157 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/EmbeddedResourceHttpHandler.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/EmbeddedResourceHttpHandler.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -57,7 +57,8 @@
     const UriComponents& uri,
     const Arguments& headers,
     const GetArguments& arguments,
-    const std::string&)
+    const char* /*bodyData*/,
+    size_t /*bodySize*/)
   {
     if (!Toolbox::IsChildUri(baseUri_, uri))
     {
--- a/Core/HttpServer/EmbeddedResourceHttpHandler.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/EmbeddedResourceHttpHandler.h	Wed Jul 01 13:16:12 2015 +0200
@@ -56,6 +56,7 @@
       const UriComponents& uri,
       const Arguments& headers,
       const GetArguments& arguments,
-      const std::string&);
+      const char* /*bodyData*/,
+      size_t /*bodySize*/);
   };
 }
--- a/Core/HttpServer/FilesystemHttpHandler.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/FilesystemHttpHandler.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -130,7 +130,8 @@
     const UriComponents& uri,
     const Arguments& headers,
     const GetArguments& arguments,
-    const std::string&)
+    const char* /*bodyData*/,
+    size_t /*bodySize*/)
   {
     if (!Toolbox::IsChildUri(pimpl_->baseUri_, uri))
     {
--- a/Core/HttpServer/FilesystemHttpHandler.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/FilesystemHttpHandler.h	Wed Jul 01 13:16:12 2015 +0200
@@ -58,7 +58,8 @@
       const UriComponents& uri,
       const Arguments& headers,
       const GetArguments& arguments,
-      const std::string&);
+      const char* /*bodyData*/,
+      size_t /*bodySize*/);
 
     bool IsListDirectoryContent() const
     {
--- a/Core/HttpServer/HttpToolbox.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/HttpToolbox.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -199,7 +199,6 @@
                               const std::string& uri)
   {
     IHttpHandler::Arguments headers;  // No HTTP header
-    std::string body;  // No body for a GET request
 
     UriComponents curi;
     IHttpHandler::GetArguments getArguments;
@@ -208,7 +207,8 @@
     StringHttpOutput stream;
     HttpOutput http(stream, false /* no keep alive */);
 
-    if (handler.Handle(http, HttpMethod_Get, curi, headers, getArguments, body))
+    if (handler.Handle(http, HttpMethod_Get, curi, headers, getArguments, 
+                       NULL /* no body for GET */, 0))
     {
       stream.GetOutput(output);
       return true;
--- a/Core/HttpServer/IHttpHandler.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/IHttpHandler.h	Wed Jul 01 13:16:12 2015 +0200
@@ -56,6 +56,7 @@
                         const UriComponents& uri,
                         const Arguments& headers,
                         const GetArguments& getArguments,
-                        const std::string& body) = 0;
+                        const char* bodyData,
+                        size_t bodySize) = 0;
   };
 }
--- a/Core/HttpServer/MongooseServer.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -622,6 +622,9 @@
 
 
     // Extract the body of the request for PUT and POST
+
+    // TODO Avoid unneccessary memcopy of the body
+
     std::string body;
     if (method == HttpMethod_Post ||
         method == HttpMethod_Put)
@@ -689,7 +692,7 @@
     {
       if (that->HasHandler())
       {
-        found = that->GetHandler().Handle(output, method, uri, headers, argumentsGET, body);
+        found = that->GetHandler().Handle(output, method, uri, headers, argumentsGET, body.c_str(), body.size());
       }
     }
     catch (OrthancException& e)
--- a/Core/RestApi/RestApi.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/RestApi/RestApi.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -51,7 +51,8 @@
       HttpMethod method_;
       const IHttpHandler::Arguments& headers_;
       const IHttpHandler::Arguments& getArguments_;
-      const std::string& postData_;
+      const char* bodyData_;
+      size_t bodySize_;
 
     public:
       HttpHandlerVisitor(RestApi& api,
@@ -59,13 +60,15 @@
                          HttpMethod method,
                          const IHttpHandler::Arguments& headers,
                          const IHttpHandler::Arguments& getArguments,
-                         const std::string& postData) :
+                         const char* bodyData,
+                         size_t bodySize) :
         api_(api),
         output_(output),
         method_(method),
         headers_(headers),
         getArguments_(getArguments),
-        postData_(postData)
+        bodyData_(bodyData),
+        bodySize_(bodySize)
       {
       }
 
@@ -87,7 +90,7 @@
 
             case HttpMethod_Post:
             {
-              RestApiPostCall call(output_, api_, headers_, components, trailing, uri, postData_);
+              RestApiPostCall call(output_, api_, headers_, components, trailing, uri, bodyData_, bodySize_);
               resource.Handle(call);
               return true;
             }
@@ -101,7 +104,7 @@
 
             case HttpMethod_Put:
             {
-              RestApiPutCall call(output_, api_, headers_, components, trailing, uri, postData_);
+              RestApiPutCall call(output_, api_, headers_, components, trailing, uri, bodyData_, bodySize_);
               resource.Handle(call);
               return true;
             }
@@ -161,7 +164,8 @@
                        const UriComponents& uri,
                        const Arguments& headers,
                        const GetArguments& getArguments,
-                       const std::string& postData)
+                       const char* bodyData,
+                       size_t bodySize)
   {
     RestApiOutput wrappedOutput(output, method);
 
@@ -191,7 +195,7 @@
     Arguments compiled;
     HttpToolbox::CompileGetArguments(compiled, getArguments);
 
-    HttpHandlerVisitor visitor(*this, wrappedOutput, method, headers, compiled, postData);
+    HttpHandlerVisitor visitor(*this, wrappedOutput, method, headers, compiled, bodyData, bodySize);
 
     if (root_.LookupResource(uri, visitor))
     {
--- a/Core/RestApi/RestApi.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/RestApi/RestApi.h	Wed Jul 01 13:16:12 2015 +0200
@@ -51,7 +51,8 @@
                         const UriComponents& uri,
                         const Arguments& headers,
                         const GetArguments& getArguments,
-                        const std::string& postData);
+                        const char* bodyData,
+                        size_t bodySize);
 
     void Register(const std::string& path,
                   RestApiGetCall::Handler handler);
--- a/Core/RestApi/RestApiPostCall.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/RestApi/RestApiPostCall.h	Wed Jul 01 13:16:12 2015 +0200
@@ -39,7 +39,8 @@
   class RestApiPostCall : public RestApiCall
   {
   private:
-    const std::string& data_;
+    const char* bodyData_;
+    size_t bodySize_;
 
   public:
     typedef void (*Handler) (RestApiPostCall& call);
@@ -50,20 +51,32 @@
                     const IHttpHandler::Arguments& uriComponents,
                     const UriComponents& trailing,
                     const UriComponents& fullUri,
-                    const std::string& data) :
+                    const char* bodyData,
+                    size_t bodySize) :
       RestApiCall(output, context, httpHeaders, uriComponents, trailing, fullUri),
-      data_(data)
+      bodyData_(bodyData),
+      bodySize_(bodySize)
     {
     }
 
-    const std::string& GetPostBody() const
+    const char* GetBodyData() const
+    {
+      return bodyData_;
+    }
+
+    size_t GetBodySize() const
     {
-      return data_;
+      return bodySize_;
+    }
+
+    void BodyToString(std::string& result) const
+    {
+      result.assign(bodyData_, bodySize_);
     }
 
     virtual bool ParseJsonRequest(Json::Value& result) const
     {
-      return ParseJsonRequestInternal(result, GetPostBody().c_str());
+      return ParseJsonRequestInternal(result, bodyData_);
     }      
   };
 }
--- a/Core/RestApi/RestApiPutCall.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/RestApi/RestApiPutCall.h	Wed Jul 01 13:16:12 2015 +0200
@@ -39,7 +39,8 @@
   class RestApiPutCall : public RestApiCall
   {
   private:
-    const std::string& data_;
+    const char* bodyData_;
+    size_t bodySize_;
 
   public:
     typedef void (*Handler) (RestApiPutCall& call);
@@ -50,20 +51,32 @@
                    const IHttpHandler::Arguments& uriComponents,
                    const UriComponents& trailing,
                    const UriComponents& fullUri,
-                   const std::string& data) :
+                   const char* bodyData,
+                   size_t bodySize) :
       RestApiCall(output, context, httpHeaders, uriComponents, trailing, fullUri),
-      data_(data)
+      bodyData_(bodyData),
+      bodySize_(bodySize)
     {
     }
 
-    const std::string& GetPutBody() const
+    const char* GetBodyData() const
+    {
+      return bodyData_;
+    }
+
+    size_t GetBodySize() const
     {
-      return data_;
+      return bodySize_;
+    }
+
+    void BodyToString(std::string& result) const
+    {
+      result.assign(bodyData_, bodySize_);
     }
 
     virtual bool ParseJsonRequest(Json::Value& result) const
     {
-      return ParseJsonRequestInternal(result, GetPutBody().c_str());
+      return ParseJsonRequestInternal(result, bodyData_);
     }      
   };
 }
--- a/Core/Toolbox.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/Toolbox.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -683,15 +683,16 @@
             digest[4]);
   }
 
-  bool Toolbox::IsSHA1(const std::string& str)
+  bool Toolbox::IsSHA1(const char* str,
+                       size_t size)
   {
-    if (str.size() == 0)
+    if (size == 0)
     {
       return false;
     }
 
-    const char* start = &str[0];
-    const char* end = start + str.size();
+    const char* start = str;
+    const char* end = str + size;
 
     // Trim the beginning of the string
     while (start < end)
@@ -747,6 +748,19 @@
   }
 
 
+  bool Toolbox::IsSHA1(const std::string& s)
+  {
+    if (s.size() == 0)
+    {
+      return false;
+    }
+    else
+    {
+      return IsSHA1(s.c_str(), s.size());
+    }
+  }
+
+
 #if BOOST_HAS_DATE_TIME == 1
   std::string Toolbox::GetNowIsoString()
   {
--- a/Core/Toolbox.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Core/Toolbox.h	Wed Jul 01 13:16:12 2015 +0200
@@ -100,7 +100,10 @@
     void ComputeSHA1(std::string& result,
                      const std::string& data);
 
-    bool IsSHA1(const std::string& str);
+    bool IsSHA1(const char* str,
+                size_t size);
+
+    bool IsSHA1(const std::string& s);
 
     void DecodeBase64(std::string& result, 
                       const std::string& data);
--- a/OrthancServer/OrthancHttpHandler.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancHttpHandler.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -43,14 +43,15 @@
                                   const UriComponents& uri,
                                   const Arguments& headers,
                                   const GetArguments& getArguments,
-                                  const std::string& body)
+                                  const char* bodyData,
+                                  size_t bodySize)
   {
     bool found = false;
 
     for (Handlers::const_iterator it = handlers_.begin(); 
          it != handlers_.end() && !found; ++it) 
     {
-      found = (*it)->Handle(output, method, uri, headers, getArguments, body);
+      found = (*it)->Handle(output, method, uri, headers, getArguments, bodyData, bodySize);
     }
 
     return found;
--- a/OrthancServer/OrthancHttpHandler.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancHttpHandler.h	Wed Jul 01 13:16:12 2015 +0200
@@ -54,7 +54,8 @@
                         const UriComponents& uri,
                         const Arguments& headers,
                         const GetArguments& getArguments,
-                        const std::string& body);
+                        const char* bodyData,
+                        size_t bodySize);
 
     void Register(IHttpHandler& handler,
                   bool isOrthancRestApi);
--- a/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestApi.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -73,13 +73,15 @@
   {
     ServerContext& context = OrthancRestApi::GetContext(call);
 
-    const std::string& postData = call.GetPostBody();
-    if (postData.size() == 0)
+    if (call.GetBodySize() == 0)
     {
       return;
     }
 
-    LOG(INFO) << "Receiving a DICOM file of " << postData.size() << " bytes through HTTP";
+    LOG(INFO) << "Receiving a DICOM file of " << call.GetBodySize() << " bytes through HTTP";
+
+    // TODO Remove unneccessary memcpy
+    std::string postData(call.GetBodyData(), call.GetBodySize());
 
     DicomInstanceToStore toStore;
     toStore.SetBuffer(postData);
--- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -82,12 +82,13 @@
    ***************************************************************************/
 
   static bool MergeQueryAndTemplate(DicomMap& result,
-                                    const std::string& postData)
+                                    const char* postData,
+                                    size_t postSize)
   {
     Json::Value query;
     Json::Reader reader;
 
-    if (!reader.parse(postData, query) ||
+    if (!reader.parse(postData, postData + postSize, query) ||
         query.type() != Json::objectValue)
     {
       return false;
@@ -169,7 +170,7 @@
 
     DicomMap fields;
     DicomMap::SetupFindPatientTemplate(fields);
-    if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
+    if (!MergeQueryAndTemplate(fields, call.GetBodyData(), call.GetBodySize()))
     {
       return;
     }
@@ -193,7 +194,7 @@
 
     DicomMap fields;
     DicomMap::SetupFindStudyTemplate(fields);
-    if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
+    if (!MergeQueryAndTemplate(fields, call.GetBodyData(), call.GetBodySize()))
     {
       return;
     }
@@ -223,7 +224,7 @@
 
     DicomMap fields;
     DicomMap::SetupFindSeriesTemplate(fields);
-    if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
+    if (!MergeQueryAndTemplate(fields, call.GetBodyData(), call.GetBodySize()))
     {
       return;
     }
@@ -254,7 +255,7 @@
 
     DicomMap fields;
     DicomMap::SetupFindInstanceTemplate(fields);
-    if (!MergeQueryAndTemplate(fields, call.GetPostBody()))
+    if (!MergeQueryAndTemplate(fields, call.GetBodyData(), call.GetBodySize()))
     {
       return;
     }
@@ -287,7 +288,7 @@
 
     DicomMap m;
     DicomMap::SetupFindPatientTemplate(m);
-    if (!MergeQueryAndTemplate(m, call.GetPostBody()))
+    if (!MergeQueryAndTemplate(m, call.GetBodyData(), call.GetBodySize()))
     {
       return;
     }
@@ -307,7 +308,7 @@
       FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i), true);
 
       DicomMap::SetupFindStudyTemplate(m);
-      if (!MergeQueryAndTemplate(m, call.GetPostBody()))
+      if (!MergeQueryAndTemplate(m, call.GetBodyData(), call.GetBodySize()))
       {
         return;
       }
@@ -325,7 +326,7 @@
         FromDcmtkBridge::ToJson(study, studies.GetAnswer(j), true);
 
         DicomMap::SetupFindSeriesTemplate(m);
-        if (!MergeQueryAndTemplate(m, call.GetPostBody()))
+        if (!MergeQueryAndTemplate(m, call.GetBodyData(), call.GetBodySize()))
         {
           return;
         }
@@ -474,10 +475,13 @@
   {
     size_t index = boost::lexical_cast<size_t>(call.GetUriComponent("index", ""));
 
-    LOG(WARNING) << "Driving C-Move SCU on modality: " << call.GetPostBody();
+    std::string modality;
+    call.BodyToString(modality);
+
+    LOG(WARNING) << "Driving C-Move SCU on modality: " << modality;
 
     QueryAccessor query(call);
-    query->Retrieve(call.GetPostBody(), index);
+    query->Retrieve(modality, index);
 
     // Retrieve has succeeded
     call.GetOutput().AnswerBuffer("{}", "application/json");
@@ -486,10 +490,13 @@
 
   static void RetrieveAllAnswers(RestApiPostCall& call)
   {
-    LOG(WARNING) << "Driving C-Move SCU on modality: " << call.GetPostBody();
+    std::string modality;
+    call.BodyToString(modality);
+
+    LOG(WARNING) << "Driving C-Move SCU on modality: " << modality;
 
     QueryAccessor query(call);
-    query->Retrieve(call.GetPostBody());
+    query->Retrieve(modality);
 
     // Retrieve has succeeded
     call.GetOutput().AnswerBuffer("{}", "application/json");
@@ -562,11 +569,14 @@
     ServerContext& context = OrthancRestApi::GetContext(call);
 
     Json::Value request;
-    if (Toolbox::IsSHA1(call.GetPostBody()))
+    if (Toolbox::IsSHA1(call.GetBodyData(), call.GetBodySize()))
     {
+      std::string s;
+      call.BodyToString(s);
+
       // This is for compatibility with Orthanc <= 0.5.1.
       request = Json::arrayValue;
-      request.append(Toolbox::StripSpaces(call.GetPostBody()));
+      request.append(Toolbox::StripSpaces(s));
     }
     else if (!call.ParseJsonRequest(request))
     {
@@ -797,7 +807,7 @@
   {
     Json::Value json;
     Json::Reader reader;
-    if (reader.parse(call.GetPutBody(), json))
+    if (reader.parse(call.GetBodyData(), call.GetBodyData() + call.GetBodySize(), json))
     {
       RemoteModalityParameters modality;
       modality.FromJson(json);
@@ -818,7 +828,7 @@
   {
     Json::Value json;
     Json::Reader reader;
-    if (reader.parse(call.GetPutBody(), json))
+    if (reader.parse(call.GetBodyData(), call.GetBodyData() + call.GetBodySize(), json))
     {
       OrthancPeerParameters peer;
       peer.FromJson(json);
--- a/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestResources.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -121,14 +121,17 @@
     ServerContext& context = OrthancRestApi::GetContext(call);
 
     std::string publicId = call.GetUriComponent("id", "");
-    std::string s = Toolbox::StripSpaces(call.GetPutBody());
 
-    if (s == "0")
+    std::string body;
+    call.BodyToString(body);
+    body = Toolbox::StripSpaces(body);
+
+    if (body == "0")
     {
       context.GetIndex().SetProtectedPatient(publicId, false);
       call.GetOutput().AnswerBuffer("", "text/plain");
     }
-    else if (s == "1")
+    else if (body == "1")
     {
       context.GetIndex().SetProtectedPatient(publicId, true);
       call.GetOutput().AnswerBuffer("", "text/plain");
@@ -160,7 +163,9 @@
     std::string dicom;
     context.ReadFile(dicom, publicId, FileContentType_Dicom);
 
-    Toolbox::WriteFile(dicom, call.GetPostBody());
+    std::string target;
+    call.BodyToString(target);
+    Toolbox::WriteFile(dicom, target);
 
     call.GetOutput().AnswerBuffer("{}", "application/json");
   }
@@ -394,7 +399,9 @@
     std::string publicId = call.GetUriComponent("id", "");
     std::string name = call.GetUriComponent("name", "");
     MetadataType metadata = StringToMetadata(name);
-    std::string value = call.GetPutBody();
+
+    std::string value;
+    call.BodyToString(value);
 
     if (metadata >= MetadataType_StartUser &&
         metadata <= MetadataType_EndUser)
@@ -604,12 +611,10 @@
     std::string publicId = call.GetUriComponent("id", "");
     std::string name = call.GetUriComponent("name", "");
 
-    const void* data = call.GetPutBody().size() ? &call.GetPutBody()[0] : NULL;
-
     FileContentType contentType = StringToContentType(name);
     if (contentType >= FileContentType_StartUser &&  // It is forbidden to modify internal attachments
         contentType <= FileContentType_EndUser &&
-        context.AddAttachment(publicId, StringToContentType(name), data, call.GetPutBody().size()))
+        context.AddAttachment(publicId, StringToContentType(name), call.GetBodyData(), call.GetBodySize()))
     {
       call.GetOutput().AnswerBuffer("{}", "application/json");
     }
@@ -825,7 +830,8 @@
   {
     typedef std::list< std::pair<ResourceType, std::string> >  Resources;
 
-    std::string tag = call.GetPostBody();
+    std::string tag;
+    call.BodyToString(tag);
     Resources resources;
 
     OrthancRestApi::GetIndex(call).LookupIdentifier(resources, tag);
--- a/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -100,9 +100,12 @@
     std::string result;
     ServerContext& context = OrthancRestApi::GetContext(call);
 
+    std::string command;
+    call.BodyToString(command);
+
     {
       LuaScripting::Locker locker(context.GetLua());
-      locker.GetLua().Execute(result, call.GetPostBody());
+      locker.GetLua().Execute(result, command);
     }
 
     call.GetOutput().AnswerBuffer(result, "text/plain");
--- a/Plugins/Engine/OrthancPlugins.cpp	Wed Jul 01 12:30:19 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Wed Jul 01 13:16:12 2015 +0200
@@ -231,7 +231,8 @@
                               const UriComponents& uri,
                               const Arguments& headers,
                               const GetArguments& getArguments,
-                              const std::string& postData)
+                              const char* bodyData,
+                              size_t bodySize)
   {
     std::string flatUri = Toolbox::FlattenUri(uri);
     OrthancPluginRestCallback callback = NULL;
@@ -308,8 +309,8 @@
     request.groups = (cgroups.size() ? &cgroups[0] : NULL);
     request.groupsCount = cgroups.size();
     request.getCount = getArguments.size();
-    request.body = (postData.size() ? &postData[0] : NULL);
-    request.bodySize = postData.size();
+    request.body = bodyData;
+    request.bodySize = bodySize;
     request.headersCount = headers.size();
     
     if (getArguments.size() > 0)
@@ -649,9 +650,6 @@
     UriComponents uri;
     Toolbox::SplitUriComponents(uri, p.uri);
 
-    // TODO Avoid unecessary memcpy
-    std::string body(p.body, p.bodySize);
-
     StringHttpOutput stream;
     HttpOutput http(stream, false /* no keep alive */);
 
@@ -664,13 +662,13 @@
 
     if (afterPlugins)
     {
-      ok = Handle(http, method, uri, headers, getArguments, body);
+      ok = Handle(http, method, uri, headers, getArguments, p.body, p.bodySize);
     }
     
     if (!ok)
     {
       ok = (pimpl_->restApi_ != NULL &&
-            pimpl_->restApi_->Handle(http, method, uri, headers, getArguments, body));
+            pimpl_->restApi_->Handle(http, method, uri, headers, getArguments, p.body, p.bodySize));
     }
 
     if (ok)
@@ -696,7 +694,6 @@
 
     IHttpHandler::Arguments headers;  // No HTTP header
     IHttpHandler::GetArguments getArguments;  // No GET argument for POST/PUT
-    std::string body;  // No body for DELETE
 
     StringHttpOutput stream;
     HttpOutput http(stream, false /* no keep alive */);
@@ -709,13 +706,15 @@
 
     if (afterPlugins)
     {
-      ok = Handle(http, HttpMethod_Delete, uri, headers, getArguments, body);
+      ok = Handle(http, HttpMethod_Delete, uri, headers, getArguments, 
+                  NULL /* no body for DELETE */, 0);
     }
 
     if (!ok)
     {
       ok = (pimpl_->restApi_ != NULL &&
-            pimpl_->restApi_->Handle(http, HttpMethod_Delete, uri, headers, getArguments, body));
+            pimpl_->restApi_->Handle(http, HttpMethod_Delete, uri, headers, getArguments, 
+                                     NULL /* no body for DELETE */, 0));
     }
 
     if (!ok)
--- a/Plugins/Engine/OrthancPlugins.h	Wed Jul 01 12:30:19 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.h	Wed Jul 01 13:16:12 2015 +0200
@@ -106,7 +106,8 @@
                         const UriComponents& uri,
                         const Arguments& headers,
                         const GetArguments& getArguments,
-                        const std::string& postData);
+                        const char* bodyData,
+                        size_t bodySize);
 
     virtual bool InvokeService(_OrthancPluginService service,
                                const void* parameters);