# HG changeset patch # User Sebastien Jodogne # Date 1559899594 -7200 # Node ID 9019279dbfd793280f2be896b9a1c1a5a64ce52a # Parent 4981405e6c5c134ed6c4671ec106ccfa4164368c new plugin c++ wrapper: MultipartRestCallback diff -r 4981405e6c5c -r 9019279dbfd7 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Thu Jun 06 21:35:05 2019 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Fri Jun 07 11:26:34 2019 +0200 @@ -4142,6 +4142,16 @@ assert(handler_ != NULL); // TODO => multipart parsing + + OrthancPluginErrorCode error = + parameters_.addPart(handler_, "content-type", 0 /* headers */, NULL, NULL, + data, size); + + if (error != OrthancPluginErrorCode_Success) + { + errorDictionary_.LogError(error, true); + throw OrthancException(static_cast(error)); + } } virtual void Execute(HttpOutput& output) @@ -4195,7 +4205,8 @@ std::string contentType = "TODO"; // TODO - OrthancPluginMultipartRestHandler* handler = (*it)->GetParameters().factory( + OrthancPluginMultipartRestHandler* handler = (*it)->GetParameters().createHandler( + (*it)->GetParameters().factory, convertedMethod, matcher.GetFlatUri().c_str(), contentType.c_str(), matcher.GetGroupsCount(), matcher.GetGroups(), headers.size(), headers.empty() ? NULL : &headersKeys[0], diff -r 4981405e6c5c -r 9019279dbfd7 Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Thu Jun 06 21:35:05 2019 +0200 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Fri Jun 07 11:26:34 2019 +0200 @@ -6911,22 +6911,27 @@ typedef struct _OrthancPluginMultipartRestHandler_t OrthancPluginMultipartRestHandler; - typedef OrthancPluginMultipartRestHandler* (*OrthancPluginMultipartRestFactory) ( - OrthancPluginHttpMethod method, - const char* url, - const char* contentType, - uint32_t groupsCount, - const char* const* groups, - uint32_t headersCount, - const char* const* headersKeys, - const char* const* headersValues); + typedef struct _OrthancPluginMultipartRestFactory_t OrthancPluginMultipartRestFactory; + + typedef OrthancPluginMultipartRestHandler* (*OrthancPluginMultipartRestCreateHandler) ( + OrthancPluginMultipartRestFactory* factory, + OrthancPluginHttpMethod method, + const char* url, + const char* contentType, + uint32_t groupsCount, + const char* const* groups, + uint32_t headersCount, + const char* const* headersKeys, + const char* const* headersValues); typedef OrthancPluginErrorCode (*OrthancPluginMultipartHandlerAddPart) ( OrthancPluginMultipartRestHandler* handler, + const char* contentType, uint32_t headersCount, const char* const* headersKeys, const char* const* headersValues, - const char* contentType); + const void* data, + uint32_t size); typedef OrthancPluginErrorCode (*OrthancPluginMultipartHandlerExecute) ( OrthancPluginMultipartRestHandler* handler, @@ -6937,24 +6942,27 @@ typedef struct { - const char* pathRegularExpression; - OrthancPluginMultipartRestFactory factory; - OrthancPluginMultipartHandlerAddPart addPart; - OrthancPluginMultipartHandlerExecute execute; - OrthancPluginMultipartHandlerFinalize finalize; + const char* pathRegularExpression; + OrthancPluginMultipartRestFactory* factory; + OrthancPluginMultipartRestCreateHandler createHandler; + OrthancPluginMultipartHandlerAddPart addPart; + OrthancPluginMultipartHandlerExecute execute; + OrthancPluginMultipartHandlerFinalize finalize; } _OrthancPluginMultipartRestCallback; ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterMultipartRestCallback( - OrthancPluginContext* context, - const char* pathRegularExpression, - OrthancPluginMultipartRestFactory factory, - OrthancPluginMultipartHandlerAddPart addPart, - OrthancPluginMultipartHandlerExecute execute, - OrthancPluginMultipartHandlerFinalize finalize) + OrthancPluginContext* context, + const char* pathRegularExpression, + OrthancPluginMultipartRestFactory* factory, + OrthancPluginMultipartRestCreateHandler createHandler, + OrthancPluginMultipartHandlerAddPart addPart, + OrthancPluginMultipartHandlerExecute execute, + OrthancPluginMultipartHandlerFinalize finalize) { _OrthancPluginMultipartRestCallback params; params.pathRegularExpression = pathRegularExpression; params.factory = factory; + params.createHandler = createHandler; params.addPart = addPart; params.execute = execute; params.finalize = finalize; diff -r 4981405e6c5c -r 9019279dbfd7 Plugins/Samples/Common/OrthancPluginCppWrapper.cpp --- a/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Thu Jun 06 21:35:05 2019 +0200 +++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Fri Jun 07 11:26:34 2019 +0200 @@ -1805,6 +1805,12 @@ + + + /****************************************************************** + ** JOBS + ******************************************************************/ + #if HAS_ORTHANC_PLUGIN_JOB == 1 void OrthancJob::CallbackFinalize(void* job) { @@ -2041,6 +2047,12 @@ #endif + + + /****************************************************************** + ** METRICS + ******************************************************************/ + #if HAS_ORTHANC_PLUGIN_METRICS == 1 MetricsTimer::MetricsTimer(const char* name) : name_(name) @@ -2059,6 +2071,11 @@ + + /****************************************************************** + ** HTTP CLIENT + ******************************************************************/ + #if HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 class HttpClient::RequestBodyWrapper : public boost::noncopyable { @@ -2581,4 +2598,139 @@ } #endif /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */ + + + + + + /****************************************************************** + ** MULTIPART REST SERVER + ******************************************************************/ + +#if HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER == 1 + static OrthancPluginMultipartRestHandler* MultipartRestFactory( + OrthancPluginMultipartRestFactory* factory, + OrthancPluginHttpMethod method, + const char* url, + const char* contentType, + uint32_t groupsCount, + const char* const* groups, + uint32_t headersCount, + const char* const* headersKeys, + const char* const* headersValues) + { + try + { + assert(factory != NULL); + MultipartRestCallback& that = *reinterpret_cast(factory); + + std::vector g; + g.resize(groupsCount); + + for (uint32_t i = 0; i < groupsCount; i++) + { + g[i] = groups[i]; + } + + std::map headers; + for (uint32_t i = 0; i < headersCount; i++) + { + headers[headersKeys[i]] = headersValues[i]; + } + + return reinterpret_cast( + that.CreateHandler(method, url, contentType, g, headers)); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + LogError("Exception while creating a multipart handler"); + return NULL; + } + catch (...) + { + LogError("Native exception while creating a multipart handler"); + return NULL; + } + } + + static OrthancPluginErrorCode MultipartRestAddPart( + OrthancPluginMultipartRestHandler* handler, + const char* contentType, + uint32_t headersCount, + const char* const* headersKeys, + const char* const* headersValues, + const void* data, + uint32_t size) + { + try + { + assert(handler != NULL); + std::map headers; + for (uint32_t i = 0; i < headersCount; i++) + { + headers[headersKeys[i]] = headersValues[i]; + } + + return reinterpret_cast(handler)-> + AddPart(contentType, headers, data, size); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + LogError("Exception while add a part to a multipart handler"); + return static_cast(e.GetErrorCode()); + } + catch (...) + { + LogError("Native exception while add a part to a multipart handler"); + return OrthancPluginErrorCode_Plugin; + } + } + + static OrthancPluginErrorCode MultipartRestExecute( + OrthancPluginMultipartRestHandler* handler, + OrthancPluginRestOutput* output) + { + try + { + assert(handler != NULL); + return reinterpret_cast(handler)->Execute(output); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + LogError("Exception while executing a multipart handler"); + return static_cast(e.GetErrorCode()); + } + catch (...) + { + LogError("Native exception while executing a multipart handler"); + return OrthancPluginErrorCode_Plugin; + } + } + + static void MultipartRestFinalize(OrthancPluginMultipartRestHandler* handler) + { + try + { + assert(handler != NULL); + delete reinterpret_cast(handler); + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + LogError("Exception while finalizing a multipart handler"); + } + catch (...) + { + LogError("Native exception while finalizing a multipart handler"); + } + } + + void MultipartRestCallback::Register(const std::string& regularExpression) + { + OrthancPluginRegisterMultipartRestCallback( + GetGlobalContext(), regularExpression.c_str(), + reinterpret_cast(this), + MultipartRestFactory, MultipartRestAddPart, MultipartRestExecute, MultipartRestFinalize); + } +#endif + } diff -r 4981405e6c5c -r 9019279dbfd7 Plugins/Samples/Common/OrthancPluginCppWrapper.h --- a/Plugins/Samples/Common/OrthancPluginCppWrapper.h Thu Jun 06 21:35:05 2019 +0200 +++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.h Fri Jun 07 11:26:34 2019 +0200 @@ -97,6 +97,12 @@ # define HAS_ORTHANC_PLUGIN_STREAMING_HTTP_CLIENT 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7) +# define HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER 1 +#else +# define HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER 0 +#endif + namespace OrthancPlugins @@ -365,7 +371,7 @@ uint32_t height, uint32_t pitch, void* buffer - ); + ); ~OrthancImage() { @@ -568,7 +574,7 @@ // error message. This is to avoid duplicating the details, // because "OrthancException" already does it on construction. OrthancPluginSetHttpErrorDetails - (GetGlobalContext(), output, e.GetDetails(), false); + (GetGlobalContext(), output, e.GetDetails(), false); } #endif @@ -593,12 +599,12 @@ if (isThreadSafe) { OrthancPluginRegisterRestCallbackNoLock - (GetGlobalContext(), uri.c_str(), Internals::Protect); + (GetGlobalContext(), uri.c_str(), Internals::Protect); } else { OrthancPluginRegisterRestCallback - (GetGlobalContext(), uri.c_str(), Internals::Protect); + (GetGlobalContext(), uri.c_str(), Internals::Protect); } } @@ -912,4 +918,40 @@ std::string& answerBody /* out */); }; #endif + + + +#if HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER == 1 + class MultipartRestCallback : public boost::noncopyable + { + public: + class IHandler : public boost::noncopyable + { + public: + virtual ~IHandler() + { + } + + virtual OrthancPluginErrorCode AddPart(const std::string& contentType, + const std::map& headers, + const void* data, + size_t size) = 0; + + virtual OrthancPluginErrorCode Execute(OrthancPluginRestOutput* output) = 0; + }; + + + virtual ~MultipartRestCallback() + { + } + + virtual IHandler* CreateHandler(OrthancPluginHttpMethod method, + const std::string& url, + const std::string& contentType, + const std::vector& groups, + const std::map& headers) = 0; + + void Register(const std::string& regularExpression); + }; +#endif }