comparison Plugins/Engine/OrthancPlugins.cpp @ 3399:4e8205871967

OrthancPluginRegisterMultipartRestCallback() is working
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 07 Jun 2019 14:14:31 +0200
parents 9019279dbfd7
children 962e5f00744b
comparison
equal deleted inserted replaced
3398:4acd1431e603 3399:4e8205871967
49 #include "../../Core/DicomParsing/DicomWebJsonVisitor.h" 49 #include "../../Core/DicomParsing/DicomWebJsonVisitor.h"
50 #include "../../Core/DicomParsing/FromDcmtkBridge.h" 50 #include "../../Core/DicomParsing/FromDcmtkBridge.h"
51 #include "../../Core/DicomParsing/Internals/DicomImageDecoder.h" 51 #include "../../Core/DicomParsing/Internals/DicomImageDecoder.h"
52 #include "../../Core/DicomParsing/ToDcmtkBridge.h" 52 #include "../../Core/DicomParsing/ToDcmtkBridge.h"
53 #include "../../Core/HttpServer/HttpToolbox.h" 53 #include "../../Core/HttpServer/HttpToolbox.h"
54 #include "../../Core/HttpServer/MultipartStreamReader.h"
54 #include "../../Core/Images/Image.h" 55 #include "../../Core/Images/Image.h"
55 #include "../../Core/Images/ImageProcessing.h" 56 #include "../../Core/Images/ImageProcessing.h"
56 #include "../../Core/Images/JpegReader.h" 57 #include "../../Core/Images/JpegReader.h"
57 #include "../../Core/Images/JpegWriter.h" 58 #include "../../Core/Images/JpegWriter.h"
58 #include "../../Core/Images/PngReader.h" 59 #include "../../Core/Images/PngReader.h"
1320 1321
1321 OrthancPluginHttpRequest request; 1322 OrthancPluginHttpRequest request;
1322 memset(&request, 0, sizeof(OrthancPluginHttpRequest)); 1323 memset(&request, 0, sizeof(OrthancPluginHttpRequest));
1323 1324
1324 ArgumentsToPlugin(headersKeys, headersValues, headers); 1325 ArgumentsToPlugin(headersKeys, headersValues, headers);
1326 assert(headersKeys.size() == headersValues.size());
1325 1327
1326 switch (method) 1328 switch (method)
1327 { 1329 {
1328 case HttpMethod_Get: 1330 case HttpMethod_Get:
1329 request.method = OrthancPluginHttpMethod_Get; 1331 request.method = OrthancPluginHttpMethod_Get;
1330 ArgumentsToPlugin(getKeys, getValues, getArguments); 1332 ArgumentsToPlugin(getKeys, getValues, getArguments);
1333 assert(getKeys.size() == getValues.size());
1331 break; 1334 break;
1332 1335
1333 case HttpMethod_Post: 1336 case HttpMethod_Post:
1334 request.method = OrthancPluginHttpMethod_Post; 1337 request.method = OrthancPluginHttpMethod_Post;
1335 break; 1338 break;
4105 } 4108 }
4106 } 4109 }
4107 } 4110 }
4108 4111
4109 4112
4110 class OrthancPlugins::MultipartStream : public IHttpHandler::IStream 4113 class OrthancPlugins::MultipartStream :
4114 public IHttpHandler::IStream,
4115 private MultipartStreamReader::IHandler
4111 { 4116 {
4112 private: 4117 private:
4113 OrthancPluginMultipartRestHandler* handler_; 4118 OrthancPluginMultipartRestHandler* handler_;
4114 _OrthancPluginMultipartRestCallback parameters_; 4119 _OrthancPluginMultipartRestCallback parameters_;
4120 MultipartStreamReader reader_;
4115 PluginsErrorDictionary& errorDictionary_; 4121 PluginsErrorDictionary& errorDictionary_;
4122
4123 virtual void HandlePart(const MultipartStreamReader::HttpHeaders& headers,
4124 const void* part,
4125 size_t size)
4126 {
4127 assert(handler_ != NULL);
4128
4129 std::string contentType;
4130 MultipartStreamReader::GetMainContentType(contentType, headers);
4131 Orthanc::Toolbox::ToLowerCase(contentType);
4132
4133 std::vector<const char*> headersKeys, headersValues;
4134 ArgumentsToPlugin(headersKeys, headersValues, headers);
4135 assert(headersKeys.size() == headersValues.size());
4136
4137 OrthancPluginErrorCode error = parameters_.addPart(
4138 handler_, contentType.c_str(), headersKeys.size(),
4139 headersKeys.empty() ? NULL : &headersKeys[0],
4140 headersValues.empty() ? NULL : &headersValues[0],
4141 part, size);
4142
4143 if (error != OrthancPluginErrorCode_Success)
4144 {
4145 errorDictionary_.LogError(error, true);
4146 throw OrthancException(static_cast<ErrorCode>(error));
4147 }
4148 }
4116 4149
4117 public: 4150 public:
4118 MultipartStream(OrthancPluginMultipartRestHandler* handler, 4151 MultipartStream(OrthancPluginMultipartRestHandler* handler,
4119 const _OrthancPluginMultipartRestCallback& parameters, 4152 const _OrthancPluginMultipartRestCallback& parameters,
4153 const std::string& boundary,
4120 PluginsErrorDictionary& errorDictionary) : 4154 PluginsErrorDictionary& errorDictionary) :
4121 handler_(handler), 4155 handler_(handler),
4122 parameters_(parameters), 4156 parameters_(parameters),
4157 reader_(boundary),
4123 errorDictionary_(errorDictionary) 4158 errorDictionary_(errorDictionary)
4124 { 4159 {
4125 if (handler_ == NULL) 4160 if (handler_ == NULL)
4126 { 4161 {
4127 throw OrthancException(ErrorCode_Plugin, "The plugin has not created a multipart stream handler"); 4162 throw OrthancException(ErrorCode_Plugin, "The plugin has not created a multipart stream handler");
4128 } 4163 }
4164
4165 reader_.SetHandler(*this);
4129 } 4166 }
4130 4167
4131 virtual ~MultipartStream() 4168 virtual ~MultipartStream()
4132 { 4169 {
4133 if (handler_ != NULL) 4170 if (handler_ != NULL)
4137 } 4174 }
4138 4175
4139 virtual void AddBodyChunk(const void* data, 4176 virtual void AddBodyChunk(const void* data,
4140 size_t size) 4177 size_t size)
4141 { 4178 {
4179 reader_.AddChunk(data, size);
4180 }
4181
4182 virtual void Execute(HttpOutput& output)
4183 {
4142 assert(handler_ != NULL); 4184 assert(handler_ != NULL);
4143 4185
4144 // TODO => multipart parsing 4186 reader_.CloseStream();
4145
4146 OrthancPluginErrorCode error =
4147 parameters_.addPart(handler_, "content-type", 0 /* headers */, NULL, NULL,
4148 data, size);
4149
4150 if (error != OrthancPluginErrorCode_Success)
4151 {
4152 errorDictionary_.LogError(error, true);
4153 throw OrthancException(static_cast<ErrorCode>(error));
4154 }
4155 }
4156
4157 virtual void Execute(HttpOutput& output)
4158 {
4159 assert(handler_ != NULL);
4160 4187
4161 PImpl::PluginHttpOutput pluginOutput(output); 4188 PImpl::PluginHttpOutput pluginOutput(output);
4162 4189
4163 OrthancPluginErrorCode error = parameters_.execute( 4190 OrthancPluginErrorCode error = parameters_.execute(
4164 handler_, reinterpret_cast<OrthancPluginRestOutput*>(&pluginOutput)); 4191 handler_, reinterpret_cast<OrthancPluginRestOutput*>(&pluginOutput));
4185 { 4212 {
4186 LOG(INFO) << "Delegating HTTP multipart request to plugin for URI: " << matcher.GetFlatUri(); 4213 LOG(INFO) << "Delegating HTTP multipart request to plugin for URI: " << matcher.GetFlatUri();
4187 4214
4188 std::vector<const char*> headersKeys, headersValues; 4215 std::vector<const char*> headersKeys, headersValues;
4189 ArgumentsToPlugin(headersKeys, headersValues, headers); 4216 ArgumentsToPlugin(headersKeys, headersValues, headers);
4217 assert(headersKeys.size() == headersValues.size());
4190 4218
4191 OrthancPluginHttpMethod convertedMethod; 4219 OrthancPluginHttpMethod convertedMethod;
4192 switch (method) 4220 switch (method)
4193 { 4221 {
4194 case HttpMethod_Post: 4222 case HttpMethod_Post:
4201 4229
4202 default: 4230 default:
4203 throw OrthancException(ErrorCode_ParameterOutOfRange); 4231 throw OrthancException(ErrorCode_ParameterOutOfRange);
4204 } 4232 }
4205 4233
4206 std::string contentType = "TODO"; // TODO 4234 std::string multipartContentType;
4235 if (!MultipartStreamReader::GetMainContentType(multipartContentType, headers))
4236 {
4237 LOG(INFO) << "Missing Content-Type HTTP header, prevents streaming the body";
4238 continue;
4239 }
4240
4241 std::string contentType, subType, boundary;
4242 if (!MultipartStreamReader::ParseMultipartContentType
4243 (contentType, subType, boundary, multipartContentType))
4244 {
4245 LOG(INFO) << "Invalid Content-Type HTTP header, "
4246 << "prevents streaming the body: \"" << multipartContentType << "\"";
4247 continue;
4248 }
4207 4249
4208 OrthancPluginMultipartRestHandler* handler = (*it)->GetParameters().createHandler( 4250 OrthancPluginMultipartRestHandler* handler = (*it)->GetParameters().createHandler(
4209 (*it)->GetParameters().factory, 4251 (*it)->GetParameters().factory,
4210 convertedMethod, matcher.GetFlatUri().c_str(), contentType.c_str(), 4252 convertedMethod, matcher.GetFlatUri().c_str(), contentType.c_str(), subType.c_str(),
4211 matcher.GetGroupsCount(), matcher.GetGroups(), headers.size(), 4253 matcher.GetGroupsCount(), matcher.GetGroups(), headers.size(),
4212 headers.empty() ? NULL : &headersKeys[0], 4254 headers.empty() ? NULL : &headersKeys[0],
4213 headers.empty() ? NULL : &headersValues[0]); 4255 headers.empty() ? NULL : &headersValues[0]);
4214 4256
4215 return new MultipartStream(handler, (*it)->GetParameters(), GetErrorDictionary()); 4257 return new MultipartStream(handler, (*it)->GetParameters(), boundary, GetErrorDictionary());
4216 } 4258 }
4217 } 4259 }
4218 4260
4219 return NULL; 4261 return NULL;
4220 } 4262 }