comparison Plugins/Engine/OrthancPlugins.cpp @ 2957:ccf61f6e22ef

New function in the SDK: "OrthancPluginSetHttpErrorDetails()"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 03 Dec 2018 17:14:55 +0100
parents bfee0b9f3209
children 74a5a7fd6e0e
comparison
equal deleted inserted replaced
2956:bfee0b9f3209 2957:ccf61f6e22ef
317 boost::mutex contextMutex_; 317 boost::mutex contextMutex_;
318 ServerContext* context_; 318 ServerContext* context_;
319 319
320 320
321 public: 321 public:
322 class PluginHttpOutput : public boost::noncopyable
323 {
324 private:
325 HttpOutput& output_;
326 std::auto_ptr<std::string> errorDetails_;
327
328 public:
329 PluginHttpOutput(HttpOutput& output) :
330 output_(output)
331 {
332 }
333
334 HttpOutput& GetOutput()
335 {
336 return output_;
337 }
338
339 void SetErrorDetails(const std::string& details)
340 {
341 errorDetails_.reset(new std::string(details));
342 }
343
344 bool HasErrorDetails() const
345 {
346 return errorDetails_.get() != NULL;
347 }
348
349 const std::string& GetErrorDetails() const
350 {
351 if (errorDetails_.get() == NULL)
352 {
353 throw OrthancException(ErrorCode_BadSequenceOfCalls);
354 }
355 else
356 {
357 return *errorDetails_;
358 }
359 }
360 };
361
362
322 class RestCallback : public boost::noncopyable 363 class RestCallback : public boost::noncopyable
323 { 364 {
324 private: 365 private:
325 boost::regex regex_; 366 boost::regex regex_;
326 OrthancPluginRestCallback callback_; 367 OrthancPluginRestCallback callback_;
327 bool lock_; 368 bool lock_;
328 369
329 OrthancPluginErrorCode InvokeInternal(HttpOutput& output, 370 OrthancPluginErrorCode InvokeInternal(PluginHttpOutput& output,
330 const std::string& flatUri, 371 const std::string& flatUri,
331 const OrthancPluginHttpRequest& request) 372 const OrthancPluginHttpRequest& request)
332 { 373 {
333 return callback_(reinterpret_cast<OrthancPluginRestOutput*>(&output), 374 return callback_(reinterpret_cast<OrthancPluginRestOutput*>(&output),
334 flatUri.c_str(), 375 flatUri.c_str(),
349 { 390 {
350 return regex_; 391 return regex_;
351 } 392 }
352 393
353 OrthancPluginErrorCode Invoke(boost::recursive_mutex& restCallbackMutex, 394 OrthancPluginErrorCode Invoke(boost::recursive_mutex& restCallbackMutex,
354 HttpOutput& output, 395 PluginHttpOutput& output,
355 const std::string& flatUri, 396 const std::string& flatUri,
356 const OrthancPluginHttpRequest& request) 397 const OrthancPluginHttpRequest& request)
357 { 398 {
358 if (lock_) 399 if (lock_)
359 { 400 {
1023 request.headersKeys = &headersKeys[0]; 1064 request.headersKeys = &headersKeys[0];
1024 request.headersValues = &headersValues[0]; 1065 request.headersValues = &headersValues[0];
1025 } 1066 }
1026 1067
1027 assert(callback != NULL); 1068 assert(callback != NULL);
1028 OrthancPluginErrorCode error = callback->Invoke(pimpl_->restCallbackMutex_, output, flatUri, request); 1069
1070 PImpl::PluginHttpOutput pluginOutput(output);
1071
1072 OrthancPluginErrorCode error = callback->Invoke(pimpl_->restCallbackMutex_, pluginOutput, flatUri, request);
1029 1073
1030 if (error == OrthancPluginErrorCode_Success && 1074 if (error == OrthancPluginErrorCode_Success &&
1031 output.IsWritingMultipart()) 1075 output.IsWritingMultipart())
1032 { 1076 {
1033 output.CloseMultipart(); 1077 output.CloseMultipart();
1038 return true; 1082 return true;
1039 } 1083 }
1040 else 1084 else
1041 { 1085 {
1042 GetErrorDictionary().LogError(error, false); 1086 GetErrorDictionary().LogError(error, false);
1043 throw OrthancException(static_cast<ErrorCode>(error)); 1087
1088 if (pluginOutput.HasErrorDetails())
1089 {
1090 throw OrthancException(static_cast<ErrorCode>(error), pluginOutput.GetErrorDetails());
1091 }
1092 else
1093 {
1094 throw OrthancException(static_cast<ErrorCode>(error));
1095 }
1044 } 1096 }
1045 } 1097 }
1046 1098
1047 1099
1048 void OrthancPlugins::SignalStoredInstance(const std::string& instanceId, 1100 void OrthancPlugins::SignalStoredInstance(const std::string& instanceId,
1245 void OrthancPlugins::AnswerBuffer(const void* parameters) 1297 void OrthancPlugins::AnswerBuffer(const void* parameters)
1246 { 1298 {
1247 const _OrthancPluginAnswerBuffer& p = 1299 const _OrthancPluginAnswerBuffer& p =
1248 *reinterpret_cast<const _OrthancPluginAnswerBuffer*>(parameters); 1300 *reinterpret_cast<const _OrthancPluginAnswerBuffer*>(parameters);
1249 1301
1250 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1302 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1251 translatedOutput->SetContentType(p.mimeType); 1303 translatedOutput.SetContentType(p.mimeType);
1252 translatedOutput->Answer(p.answer, p.answerSize); 1304 translatedOutput.Answer(p.answer, p.answerSize);
1253 } 1305 }
1254 1306
1255 1307
1256 void OrthancPlugins::Redirect(const void* parameters) 1308 void OrthancPlugins::Redirect(const void* parameters)
1257 { 1309 {
1258 const _OrthancPluginOutputPlusArgument& p = 1310 const _OrthancPluginOutputPlusArgument& p =
1259 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters); 1311 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters);
1260 1312
1261 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1313 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1262 translatedOutput->Redirect(p.argument); 1314 translatedOutput.Redirect(p.argument);
1263 } 1315 }
1264 1316
1265 1317
1266 void OrthancPlugins::SendHttpStatusCode(const void* parameters) 1318 void OrthancPlugins::SendHttpStatusCode(const void* parameters)
1267 { 1319 {
1268 const _OrthancPluginSendHttpStatusCode& p = 1320 const _OrthancPluginSendHttpStatusCode& p =
1269 *reinterpret_cast<const _OrthancPluginSendHttpStatusCode*>(parameters); 1321 *reinterpret_cast<const _OrthancPluginSendHttpStatusCode*>(parameters);
1270 1322
1271 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1323 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1272 translatedOutput->SendStatus(static_cast<HttpStatus>(p.status)); 1324 translatedOutput.SendStatus(static_cast<HttpStatus>(p.status));
1273 } 1325 }
1274 1326
1275 1327
1276 void OrthancPlugins::SendHttpStatus(const void* parameters) 1328 void OrthancPlugins::SendHttpStatus(const void* parameters)
1277 { 1329 {
1278 const _OrthancPluginSendHttpStatus& p = 1330 const _OrthancPluginSendHttpStatus& p =
1279 *reinterpret_cast<const _OrthancPluginSendHttpStatus*>(parameters); 1331 *reinterpret_cast<const _OrthancPluginSendHttpStatus*>(parameters);
1280 1332
1281 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1333 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1282 HttpStatus status = static_cast<HttpStatus>(p.status); 1334 HttpStatus status = static_cast<HttpStatus>(p.status);
1283 1335
1284 if (p.bodySize > 0 && p.body != NULL) 1336 if (p.bodySize > 0 && p.body != NULL)
1285 { 1337 {
1286 translatedOutput->SendStatus(status, p.body, p.bodySize); 1338 translatedOutput.SendStatus(status, p.body, p.bodySize);
1287 } 1339 }
1288 else 1340 else
1289 { 1341 {
1290 translatedOutput->SendStatus(status); 1342 translatedOutput.SendStatus(status);
1291 } 1343 }
1292 } 1344 }
1293 1345
1294 1346
1295 void OrthancPlugins::SendUnauthorized(const void* parameters) 1347 void OrthancPlugins::SendUnauthorized(const void* parameters)
1296 { 1348 {
1297 const _OrthancPluginOutputPlusArgument& p = 1349 const _OrthancPluginOutputPlusArgument& p =
1298 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters); 1350 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters);
1299 1351
1300 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1352 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1301 translatedOutput->SendUnauthorized(p.argument); 1353 translatedOutput.SendUnauthorized(p.argument);
1302 } 1354 }
1303 1355
1304 1356
1305 void OrthancPlugins::SendMethodNotAllowed(const void* parameters) 1357 void OrthancPlugins::SendMethodNotAllowed(const void* parameters)
1306 { 1358 {
1307 const _OrthancPluginOutputPlusArgument& p = 1359 const _OrthancPluginOutputPlusArgument& p =
1308 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters); 1360 *reinterpret_cast<const _OrthancPluginOutputPlusArgument*>(parameters);
1309 1361
1310 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1362 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1311 translatedOutput->SendMethodNotAllowed(p.argument); 1363 translatedOutput.SendMethodNotAllowed(p.argument);
1312 } 1364 }
1313 1365
1314 1366
1315 void OrthancPlugins::SetCookie(const void* parameters) 1367 void OrthancPlugins::SetCookie(const void* parameters)
1316 { 1368 {
1317 const _OrthancPluginSetHttpHeader& p = 1369 const _OrthancPluginSetHttpHeader& p =
1318 *reinterpret_cast<const _OrthancPluginSetHttpHeader*>(parameters); 1370 *reinterpret_cast<const _OrthancPluginSetHttpHeader*>(parameters);
1319 1371
1320 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1372 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1321 translatedOutput->SetCookie(p.key, p.value); 1373 translatedOutput.SetCookie(p.key, p.value);
1322 } 1374 }
1323 1375
1324 1376
1325 void OrthancPlugins::SetHttpHeader(const void* parameters) 1377 void OrthancPlugins::SetHttpHeader(const void* parameters)
1326 { 1378 {
1327 const _OrthancPluginSetHttpHeader& p = 1379 const _OrthancPluginSetHttpHeader& p =
1328 *reinterpret_cast<const _OrthancPluginSetHttpHeader*>(parameters); 1380 *reinterpret_cast<const _OrthancPluginSetHttpHeader*>(parameters);
1329 1381
1330 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1382 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1331 translatedOutput->AddHeader(p.key, p.value); 1383 translatedOutput.AddHeader(p.key, p.value);
1384 }
1385
1386
1387 void OrthancPlugins::SetHttpErrorDetails(const void* parameters)
1388 {
1389 const _OrthancPluginSetHttpErrorDetails& p =
1390 *reinterpret_cast<const _OrthancPluginSetHttpErrorDetails*>(parameters);
1391
1392 PImpl::PluginHttpOutput* output = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output);
1393 output->SetErrorDetails(p.details);
1332 } 1394 }
1333 1395
1334 1396
1335 void OrthancPlugins::CompressAndAnswerPngImage(const void* parameters) 1397 void OrthancPlugins::CompressAndAnswerPngImage(const void* parameters)
1336 { 1398 {
1355 void OrthancPlugins::CompressAndAnswerImage(const void* parameters) 1417 void OrthancPlugins::CompressAndAnswerImage(const void* parameters)
1356 { 1418 {
1357 const _OrthancPluginCompressAndAnswerImage& p = 1419 const _OrthancPluginCompressAndAnswerImage& p =
1358 *reinterpret_cast<const _OrthancPluginCompressAndAnswerImage*>(parameters); 1420 *reinterpret_cast<const _OrthancPluginCompressAndAnswerImage*>(parameters);
1359 1421
1360 HttpOutput* translatedOutput = reinterpret_cast<HttpOutput*>(p.output); 1422 HttpOutput& translatedOutput = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
1361 1423
1362 ImageAccessor accessor; 1424 ImageAccessor accessor;
1363 accessor.AssignReadOnly(Plugins::Convert(p.pixelFormat), p.width, p.height, p.pitch, p.buffer); 1425 accessor.AssignReadOnly(Plugins::Convert(p.pixelFormat), p.width, p.height, p.pitch, p.buffer);
1364 1426
1365 std::string compressed; 1427 std::string compressed;
1368 { 1430 {
1369 case OrthancPluginImageFormat_Png: 1431 case OrthancPluginImageFormat_Png:
1370 { 1432 {
1371 PngWriter writer; 1433 PngWriter writer;
1372 writer.WriteToMemory(compressed, accessor); 1434 writer.WriteToMemory(compressed, accessor);
1373 translatedOutput->SetContentType(MimeType_Png); 1435 translatedOutput.SetContentType(MimeType_Png);
1374 break; 1436 break;
1375 } 1437 }
1376 1438
1377 case OrthancPluginImageFormat_Jpeg: 1439 case OrthancPluginImageFormat_Jpeg:
1378 { 1440 {
1379 JpegWriter writer; 1441 JpegWriter writer;
1380 writer.SetQuality(p.quality); 1442 writer.SetQuality(p.quality);
1381 writer.WriteToMemory(compressed, accessor); 1443 writer.WriteToMemory(compressed, accessor);
1382 translatedOutput->SetContentType(MimeType_Jpeg); 1444 translatedOutput.SetContentType(MimeType_Jpeg);
1383 break; 1445 break;
1384 } 1446 }
1385 1447
1386 default: 1448 default:
1387 throw OrthancException(ErrorCode_ParameterOutOfRange); 1449 throw OrthancException(ErrorCode_ParameterOutOfRange);
1388 } 1450 }
1389 1451
1390 translatedOutput->Answer(compressed); 1452 translatedOutput.Answer(compressed);
1391 } 1453 }
1392 1454
1393 1455
1394 void OrthancPlugins::GetDicomForInstance(const void* parameters) 1456 void OrthancPlugins::GetDicomForInstance(const void* parameters)
1395 { 1457 {
2283 // An exception might be raised in this function if the 2345 // An exception might be raised in this function if the
2284 // connection was closed by the HTTP client. 2346 // connection was closed by the HTTP client.
2285 const _OrthancPluginAnswerBuffer& p = 2347 const _OrthancPluginAnswerBuffer& p =
2286 *reinterpret_cast<const _OrthancPluginAnswerBuffer*>(parameters); 2348 *reinterpret_cast<const _OrthancPluginAnswerBuffer*>(parameters);
2287 2349
2288 HttpOutput* output = reinterpret_cast<HttpOutput*>(p.output); 2350 HttpOutput& output = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
2289 2351
2290 std::map<std::string, std::string> headers; // No custom headers 2352 std::map<std::string, std::string> headers; // No custom headers
2291 output->SendMultipartItem(p.answer, p.answerSize, headers); 2353 output.SendMultipartItem(p.answer, p.answerSize, headers);
2292 } 2354 }
2293 2355
2294 2356
2295 void OrthancPlugins::ApplySendMultipartItem2(const void* parameters) 2357 void OrthancPlugins::ApplySendMultipartItem2(const void* parameters)
2296 { 2358 {
2297 // An exception might be raised in this function if the 2359 // An exception might be raised in this function if the
2298 // connection was closed by the HTTP client. 2360 // connection was closed by the HTTP client.
2299 const _OrthancPluginSendMultipartItem2& p = 2361 const _OrthancPluginSendMultipartItem2& p =
2300 *reinterpret_cast<const _OrthancPluginSendMultipartItem2*>(parameters); 2362 *reinterpret_cast<const _OrthancPluginSendMultipartItem2*>(parameters);
2301 HttpOutput* output = reinterpret_cast<HttpOutput*>(p.output); 2363 HttpOutput& output = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
2302 2364
2303 std::map<std::string, std::string> headers; 2365 std::map<std::string, std::string> headers;
2304 for (uint32_t i = 0; i < p.headersCount; i++) 2366 for (uint32_t i = 0; i < p.headersCount; i++)
2305 { 2367 {
2306 headers[p.headersKeys[i]] = p.headersValues[i]; 2368 headers[p.headersKeys[i]] = p.headersValues[i];
2307 } 2369 }
2308 2370
2309 output->SendMultipartItem(p.answer, p.answerSize, headers); 2371 output.SendMultipartItem(p.answer, p.answerSize, headers);
2310 } 2372 }
2311 2373
2312 2374
2313 void OrthancPlugins::DatabaseAnswer(const void* parameters) 2375 void OrthancPlugins::DatabaseAnswer(const void* parameters)
2314 { 2376 {
2506 SetCookie(parameters); 2568 SetCookie(parameters);
2507 return true; 2569 return true;
2508 2570
2509 case _OrthancPluginService_SetHttpHeader: 2571 case _OrthancPluginService_SetHttpHeader:
2510 SetHttpHeader(parameters); 2572 SetHttpHeader(parameters);
2573 return true;
2574
2575 case _OrthancPluginService_SetHttpErrorDetails:
2576 SetHttpErrorDetails(parameters);
2511 return true; 2577 return true;
2512 2578
2513 case _OrthancPluginService_LookupPatient: 2579 case _OrthancPluginService_LookupPatient:
2514 case _OrthancPluginService_LookupStudy: 2580 case _OrthancPluginService_LookupStudy:
2515 case _OrthancPluginService_LookupStudyWithAccessionNumber: 2581 case _OrthancPluginService_LookupStudyWithAccessionNumber:
2571 2637
2572 case _OrthancPluginService_StartMultipartAnswer: 2638 case _OrthancPluginService_StartMultipartAnswer:
2573 { 2639 {
2574 const _OrthancPluginStartMultipartAnswer& p = 2640 const _OrthancPluginStartMultipartAnswer& p =
2575 *reinterpret_cast<const _OrthancPluginStartMultipartAnswer*>(parameters); 2641 *reinterpret_cast<const _OrthancPluginStartMultipartAnswer*>(parameters);
2576 HttpOutput* output = reinterpret_cast<HttpOutput*>(p.output); 2642 HttpOutput& output = reinterpret_cast<PImpl::PluginHttpOutput*>(p.output)->GetOutput();
2577 output->StartMultipart(p.subType, p.contentType); 2643 output.StartMultipart(p.subType, p.contentType);
2578 return true; 2644 return true;
2579 } 2645 }
2580 2646
2581 case _OrthancPluginService_SendMultipartItem: 2647 case _OrthancPluginService_SendMultipartItem:
2582 ApplySendMultipartItem(parameters); 2648 ApplySendMultipartItem(parameters);