Mercurial > hg > orthanc
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 } |