# HG changeset patch # User Sebastien Jodogne # Date 1449649745 -3600 # Node ID 5cf2bd0abfa257ce13940641b055f431b1ed6169 # Parent d2efbe076653e355e14fb6b712e58f7540ffff38 OrthancPluginSendMultipartItem2 for DICOMweb diff -r d2efbe076653 -r 5cf2bd0abfa2 Core/HttpServer/HttpOutput.cpp --- a/Core/HttpServer/HttpOutput.cpp Tue Dec 08 15:53:35 2015 +0100 +++ b/Core/HttpServer/HttpOutput.cpp Wed Dec 09 09:29:05 2015 +0100 @@ -449,12 +449,59 @@ } - void HttpOutput::StateMachine::SendMultipartItem(const void* item, size_t length) + void HttpOutput::StateMachine::SendMultipartItem(const void* item, + size_t length, + const std::map& headers) { + if (state_ != State_WritingMultipart) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + std::string header = "--" + multipartBoundary_ + "\r\n"; - header += "Content-Type: " + multipartContentType_ + "\r\n"; - header += "Content-Length: " + boost::lexical_cast(length) + "\r\n"; - header += "MIME-Version: 1.0\r\n\r\n"; + + bool hasContentType = false; + bool hasContentLength = false; + bool hasMimeVersion = false; + + for (std::map::const_iterator + it = headers.begin(); it != headers.end(); ++it) + { + header += it->first + ": " + it->second + "\r\n"; + + std::string tmp; + Toolbox::ToLowerCase(tmp, it->first); + + if (tmp == "content-type") + { + hasContentType = true; + } + + if (tmp == "content-length") + { + hasContentLength = true; + } + + if (tmp == "mime-version") + { + hasMimeVersion = true; + } + } + + if (!hasContentType) + { + header += "Content-Type: " + multipartContentType_ + "\r\n"; + } + + if (!hasContentLength) + { + header += "Content-Length: " + boost::lexical_cast(length) + "\r\n"; + } + + if (!hasMimeVersion) + { + header += "MIME-Version: 1.0\r\n\r\n"; + } stream_.Send(false, header.c_str(), header.size()); @@ -463,7 +510,7 @@ stream_.Send(false, item, length); } - stream_.Send(false, "\r\n", 2); + stream_.Send(false, "\r\n", 2); } @@ -489,19 +536,6 @@ } - void HttpOutput::SendMultipartItem(const std::string& item) - { - if (item.size() > 0) - { - stateMachine_.SendMultipartItem(item.c_str(), item.size()); - } - else - { - stateMachine_.SendMultipartItem(NULL, 0); - } - } - - void HttpOutput::Answer(IHttpStreamAnswer& stream) { HttpCompression compression = stream.SetupHttpCompression(isGzipAllowed_, isDeflateAllowed_); diff -r d2efbe076653 -r 5cf2bd0abfa2 Core/HttpServer/HttpOutput.h --- a/Core/HttpServer/HttpOutput.h Tue Dec 08 15:53:35 2015 +0100 +++ b/Core/HttpServer/HttpOutput.h Wed Dec 09 09:29:05 2015 +0100 @@ -99,7 +99,9 @@ void StartMultipart(const std::string& subType, const std::string& contentType); - void SendMultipartItem(const void* item, size_t length); + void SendMultipartItem(const void* item, + size_t length, + const std::map& headers); void CloseMultipart(); @@ -202,11 +204,11 @@ stateMachine_.StartMultipart(subType, contentType); } - void SendMultipartItem(const std::string& item); - - void SendMultipartItem(const void* item, size_t size) + void SendMultipartItem(const void* item, + size_t size, + const std::map& headers) { - stateMachine_.SendMultipartItem(item, size); + stateMachine_.SendMultipartItem(item, size, headers); } void CloseMultipart() diff -r d2efbe076653 -r 5cf2bd0abfa2 NEWS --- a/NEWS Tue Dec 08 15:53:35 2015 +0100 +++ b/NEWS Wed Dec 09 09:29:05 2015 +0100 @@ -2,6 +2,9 @@ =============================== +* New function in plugin SDK: "OrthancPluginSendMultipartItem2()" + + Version 0.9.6 (2015/12/08) ========================== diff -r d2efbe076653 -r 5cf2bd0abfa2 Plugins/Engine/OrthancPlugins.cpp --- a/Plugins/Engine/OrthancPlugins.cpp Tue Dec 08 15:53:35 2015 +0100 +++ b/Plugins/Engine/OrthancPlugins.cpp Wed Dec 09 09:29:05 2015 +0100 @@ -1574,7 +1574,39 @@ *(p.target) = ReturnImage(result); } - + + + void OrthancPlugins::ApplySendMultipartItem(const void* parameters) + { + // An exception might be raised in this function if the + // connection was closed by the HTTP client. + const _OrthancPluginAnswerBuffer& p = + *reinterpret_cast(parameters); + + HttpOutput* output = reinterpret_cast(p.output); + + std::map headers; // No custom headers + output->SendMultipartItem(p.answer, p.answerSize, headers); + } + + + void OrthancPlugins::ApplySendMultipartItem2(const void* parameters) + { + // An exception might be raised in this function if the + // connection was closed by the HTTP client. + const _OrthancPluginSendMultipartItem2& p = + *reinterpret_cast(parameters); + HttpOutput* output = reinterpret_cast(p.output); + + std::map headers; + for (uint32_t i = 0; i < p.headersCount; i++) + { + headers[p.headersKeys[i]] = p.headersValues[i]; + } + + output->SendMultipartItem(p.answer, p.answerSize, headers); + } + void OrthancPlugins::DatabaseAnswer(const void* parameters) { @@ -1969,15 +2001,12 @@ } case _OrthancPluginService_SendMultipartItem: - { - // An exception might be raised in this function if the - // connection was closed by the HTTP client. - const _OrthancPluginAnswerBuffer& p = - *reinterpret_cast(parameters); - HttpOutput* output = reinterpret_cast(p.output); - output->SendMultipartItem(p.answer, p.answerSize); + ApplySendMultipartItem(parameters); return true; - } + + case _OrthancPluginService_SendMultipartItem2: + ApplySendMultipartItem2(parameters); + return true; case _OrthancPluginService_ReadFile: { diff -r d2efbe076653 -r 5cf2bd0abfa2 Plugins/Engine/OrthancPlugins.h --- a/Plugins/Engine/OrthancPlugins.h Tue Dec 08 15:53:35 2015 +0100 +++ b/Plugins/Engine/OrthancPlugins.h Wed Dec 09 09:29:05 2015 +0100 @@ -152,6 +152,10 @@ void ApplyLookupDictionary(const void* parameters); + void ApplySendMultipartItem(const void* parameters); + + void ApplySendMultipartItem2(const void* parameters); + void ComputeHash(_OrthancPluginService service, const void* parameters); diff -r d2efbe076653 -r 5cf2bd0abfa2 Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Tue Dec 08 15:53:35 2015 +0100 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Wed Dec 09 09:29:05 2015 +0100 @@ -114,7 +114,7 @@ #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER 0 #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER 9 -#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 5 +#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER 7 @@ -424,6 +424,7 @@ _OrthancPluginService_SendMultipartItem = 2009, _OrthancPluginService_SendHttpStatus = 2010, _OrthancPluginService_CompressAndAnswerImage = 2011, + _OrthancPluginService_SendMultipartItem2 = 2012, /* Access to the Orthanc database and API */ _OrthancPluginService_GetDicomForInstance = 3000, @@ -2719,7 +2720,7 @@ * @param subType The sub-type of the multipart answer ("mixed" or "related"). * @param contentType The MIME type of the items in the multipart answer. * @return 0 if success, or the error code if failure. - * @see OrthancPluginSendMultipartItem() + * @see OrthancPluginSendMultipartItem(), OrthancPluginSendMultipartItem2() * @ingroup REST **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginStartMultipartAnswer( @@ -2748,6 +2749,7 @@ * @param answerSize Number of bytes of the item. * @return 0 if success, or the error code if failure (this notably happens * if the connection is closed by the client). + * @see OrthancPluginSendMultipartItem2() * @ingroup REST **/ ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem( @@ -4677,6 +4679,58 @@ } + + typedef struct + { + OrthancPluginRestOutput* output; + const char* answer; + uint32_t answerSize; + uint32_t headersCount; + const char* const* headersKeys; + const char* const* headersValues; + } _OrthancPluginSendMultipartItem2; + + /** + * @brief Send an item as a part of some HTTP multipart answer, with custom headers. + * + * This function sends an item as a part of some HTTP multipart + * answer that was initiated by OrthancPluginStartMultipartAnswer(). In addition to + * OrthancPluginSendMultipartItem(), this function will set HTTP header associated + * with the item. + * + * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). + * @param output The HTTP connection to the client application. + * @param answer Pointer to the memory buffer containing the item. + * @param answerSize Number of bytes of the item. + * @param headersCount The number of HTTP headers. + * @param headersKeys Array containing the keys of the HTTP headers. + * @param headersValues Array containing the values of the HTTP headers. + * @return 0 if success, or the error code if failure (this notably happens + * if the connection is closed by the client). + * @see OrthancPluginSendMultipartItem() + * @ingroup REST + **/ + ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginSendMultipartItem2( + OrthancPluginContext* context, + OrthancPluginRestOutput* output, + const char* answer, + uint32_t answerSize, + uint32_t headersCount, + const char* const* headersKeys, + const char* const* headersValues) + { + _OrthancPluginSendMultipartItem2 params; + params.output = output; + params.answer = answer; + params.answerSize = answerSize; + params.headersCount = headersCount; + params.headersKeys = headersKeys; + params.headersValues = headersValues; + + return context->InvokeService(context, _OrthancPluginService_SendMultipartItem2, ¶ms); + } + + #ifdef __cplusplus } #endif