Mercurial > hg > orthanc
diff Plugins/Samples/Common/OrthancPluginCppWrapper.h @ 3414:b9cba6a91780
simplification
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Jun 2019 19:44:10 +0200 |
parents | f09bfdea3fc3 |
children | 2a821deece64 |
line wrap: on
line diff
--- a/Plugins/Samples/Common/OrthancPluginCppWrapper.h Tue Jun 11 14:02:57 2019 +0200 +++ b/Plugins/Samples/Common/OrthancPluginCppWrapper.h Tue Jun 11 19:44:10 2019 +0200 @@ -57,21 +57,6 @@ #endif -#if !defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE) -#define ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(major, minor, revision) \ - (defined(HAS_ORTHANC_FRAMEWORK) && \ - defined(ORTHANC_FRAMEWORK_VERSION_MAJOR) && \ - defined(ORTHANC_FRAMEWORK_VERSION_MINOR) && \ - defined(ORTHANC_FRAMEWORK_VERSION_REVISION) && \ - HAS_ORTHANC_FRAMEWORK == 1 && \ - ORTHANC_FRAMEWORK_VERSION_MAJOR > major || \ - (ORTHANC_FRAMEWORK_VERSION_MAJOR == major && \ - (ORTHANC_FRAMEWORK_VERSION_MINOR > minor || \ - (ORTHANC_FRAMEWORK_VERSION_MINOR == minor && \ - ORTHANC_FRAMEWORK_VERSION_REVISION >= revision)))) -#endif - - #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0) // The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0 # define HAS_ORTHANC_PLUGIN_FIND_MATCHER 1 @@ -113,9 +98,9 @@ #endif #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 5, 7) -# define HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER 1 +# define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER 1 #else -# define HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER 0 +# define HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER 0 #endif @@ -126,7 +111,6 @@ const char* url, const OrthancPluginHttpRequest* request); - void SetGlobalContext(OrthancPluginContext* context); bool HasGlobalContext(); @@ -936,36 +920,225 @@ - class MultipartRestCallback : public boost::noncopyable + class IChunkedRequestReader : public boost::noncopyable { public: - class IHandler : public boost::noncopyable - { - public: - virtual ~IHandler() - { - } - - virtual OrthancPluginErrorCode AddPart(const std::string& contentType, - const std::map<std::string, std::string>& headers, - const void* data, - size_t size) = 0; - - virtual OrthancPluginErrorCode Execute(OrthancPluginRestOutput* output) = 0; - }; - - - virtual ~MultipartRestCallback() + virtual ~IChunkedRequestReader() { } - virtual IHandler* CreateHandler(OrthancPluginHttpMethod method, - const std::string& url, - const std::string& contentType, - const std::string& subType, // Possibly empty - const std::vector<std::string>& groups, - const std::map<std::string, std::string>& headers) = 0; + virtual void AddChunk(const void* data, + size_t size) = 0; + + virtual void Execute(OrthancPluginRestOutput* output) = 0; + }; + + + typedef IChunkedRequestReader* (*ChunkedRestCallback) (OrthancPluginRestOutput* output, + const char* url, + const OrthancPluginHttpRequest* request); + + + namespace Internals + { +#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 + template <ChunkedRestCallback Callback> + OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output, + OrthancPluginServerChunkedRequestReader** reader, + const char* url, + const OrthancPluginHttpRequest* request) + { + try + { + switch (request->method) + { + case OrthancPluginHttpMethod_Get: + case OrthancPluginHttpMethod_Delete: + if (output == NULL || + reader != NULL || + Callback(output, url, request) != NULL) + { + return OrthancPluginErrorCode_InternalError; + } + + return OrthancPluginErrorCode_Success; + + case OrthancPluginHttpMethod_Post: + case OrthancPluginHttpMethod_Put: + if (output != NULL || + reader == NULL) + { + return OrthancPluginErrorCode_InternalError; + } + else + { + *reader = reinterpret_cast<OrthancPluginServerChunkedRequestReader*>(Callback(NULL, url, request)); + if (*reader == NULL) + { + return OrthancPluginErrorCode_Plugin; + } + } + + return OrthancPluginErrorCode_Success; + + default: + return OrthancPluginErrorCode_InternalError; + } + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { +#if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1 + if (HasGlobalContext() && + e.HasDetails()) + { + // The "false" instructs Orthanc not to log the detailed + // error message. This is to avoid duplicating the details, + // because "OrthancException" already does it on construction. + OrthancPluginSetHttpErrorDetails + (GetGlobalContext(), output, e.GetDetails(), false); + } +#endif + + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (boost::bad_lexical_cast&) + { + return OrthancPluginErrorCode_BadFileFormat; + } + catch (...) + { + return OrthancPluginErrorCode_Plugin; + } + } + + static OrthancPluginErrorCode ChunkedRequestReaderAddChunk( + OrthancPluginServerChunkedRequestReader* reader, + const void* data, + uint32_t size) + { + try + { + if (reader == NULL) + { + return OrthancPluginErrorCode_InternalError; + } - void Register(const std::string& regularExpression); - }; + reinterpret_cast<IChunkedRequestReader*>(reader)->AddChunk(data, size); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (boost::bad_lexical_cast&) + { + return OrthancPluginErrorCode_BadFileFormat; + } + catch (...) + { + return OrthancPluginErrorCode_Plugin; + } + } + + static OrthancPluginErrorCode ChunkedRequestReaderExecute( + OrthancPluginServerChunkedRequestReader* reader, + OrthancPluginRestOutput* output) + { + try + { + if (reader == NULL) + { + return OrthancPluginErrorCode_InternalError; + } + + reinterpret_cast<IChunkedRequestReader*>(reader)->Execute(output); + return OrthancPluginErrorCode_Success; + } + catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) + { + return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); + } + catch (boost::bad_lexical_cast&) + { + return OrthancPluginErrorCode_BadFileFormat; + } + catch (...) + { + return OrthancPluginErrorCode_Plugin; + } + } + + static void ChunkedRequestReaderFinalize( + OrthancPluginServerChunkedRequestReader* reader) + { + if (reader != NULL) + { + delete reinterpret_cast<IChunkedRequestReader*>(reader); + } + } + +#else + + template <ChunkedRestCallback Callback> + void ChunkedRestCompatibility(OrthancPluginRestOutput* output, + const char* url, + const OrthancPluginHttpRequest* request) + { + switch (request->method) + { + case OrthancPluginHttpMethod_Get: + case OrthancPluginHttpMethod_Delete: + if (Callback(output, url, request) != NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + return; + } + + case OrthancPluginHttpMethod_Post: + case OrthancPluginHttpMethod_Put: + { + std::auto_ptr<IChunkedRequestReader> reader(Callback(NULL, url, request)); + if (reader.get() == NULL) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + if (request->bodySize != 0) + { + reader->AddChunk(request->body, request->bodySize); + } + reader->Execute(output); + } + return; + } + + default: + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + } +#endif + } + + + template <ChunkedRestCallback Callback> + void RegisterChunkedRestCallback(const std::string& uri) + { +#if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 + OrthancPluginRegisterChunkedRestCallback( + GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>, + Internals::ChunkedRequestReaderAddChunk, + Internals::ChunkedRequestReaderExecute, + Internals::ChunkedRequestReaderFinalize); +#else + LogWarning("Performance warning: The plugin was compiled against a pre-1.5.7 version " + "of the Orthanc SDK. Multipart transfers will be entirely stored in RAM."); + OrthancPluginRegisterRestCallback( + GetGlobalContext(), uri.c_str(), + Internals::Protect< Internals::ChunkedRestCompatibility<Callback> >); +#endif + } }