changeset 86:58665d0b7609

catching exceptions in REST callbacks with a template function
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Dec 2015 10:05:51 +0100
parents 6ee987d645cd
children 8effbfc4cf28
files Plugin/Configuration.h Plugin/Plugin.cpp Plugin/QidoRs.cpp Plugin/StowRs.cpp Plugin/Wado.cpp Plugin/WadoRs.cpp
diffstat 6 files changed, 355 insertions(+), 497 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/Configuration.h	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/Configuration.h	Wed Dec 09 10:05:51 2015 +0100
@@ -23,6 +23,13 @@
 #include <orthanc/OrthancCPlugin.h>
 #include <json/value.h>
 
+#if (ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER <= 0 && \
+     ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER <= 9 && \
+     ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER <= 6)
+#  define HAS_SEND_MULTIPART_ITEM_2   0
+#else
+#  define HAS_SEND_MULTIPART_ITEM_2   1
+#endif
 
 namespace OrthancPlugins
 {
--- a/Plugin/Plugin.cpp	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/Plugin.cpp	Wed Dec 09 10:05:51 2015 +0100
@@ -38,10 +38,41 @@
 Json::Value configuration_;
 const gdcm::Dict* dictionary_ = NULL;
 
+#include "../Orthanc/Core/OrthancException.h"
+#include <boost/lexical_cast.hpp>
 
-static OrthancPluginErrorCode SwitchStudies(OrthancPluginRestOutput* output,
-                                            const char* url,
-                                            const OrthancPluginHttpRequest* request)
+
+template <OrthancPluginRestCallback Callback>
+OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output,
+                               const char* url,
+                               const OrthancPluginHttpRequest* request)
+{
+  try
+  {
+    return Callback(output, url, request);
+  }
+  catch (Orthanc::OrthancException& e)
+  {
+    OrthancPluginLogError(context_, e.What());
+    return OrthancPluginErrorCode_Plugin;
+  }
+  catch (boost::bad_lexical_cast& e)
+  {
+    OrthancPluginLogError(context_, e.what());
+    return OrthancPluginErrorCode_Plugin;
+  }
+  catch (std::runtime_error& e)
+  {
+    OrthancPluginLogError(context_, e.what());
+    return OrthancPluginErrorCode_Plugin;
+  }
+}
+
+
+
+OrthancPluginErrorCode SwitchStudies(OrthancPluginRestOutput* output,
+                                     const char* url,
+                                     const OrthancPluginHttpRequest* request)
 {
   switch (request->method)
   {
@@ -60,9 +91,9 @@
 }
 
 
-static OrthancPluginErrorCode SwitchStudy(OrthancPluginRestOutput* output,
-                                          const char* url,
-                                          const OrthancPluginHttpRequest* request)
+OrthancPluginErrorCode SwitchStudy(OrthancPluginRestOutput* output,
+                                   const char* url,
+                                   const OrthancPluginHttpRequest* request)
 {
   switch (request->method)
   {
@@ -152,20 +183,20 @@
       std::string message = "URI to the DICOMweb REST API: " + root;
       OrthancPluginLogWarning(context_, message.c_str());
 
-      Register(root, "instances", SearchForInstances);    
-      Register(root, "series", SearchForSeries);    
-      Register(root, "studies", SwitchStudies);
-      Register(root, "studies/([^/]*)", SwitchStudy);
-      Register(root, "studies/([^/]*)/instances", SearchForInstances);    
-      Register(root, "studies/([^/]*)/metadata", RetrieveStudyMetadata);
-      Register(root, "studies/([^/]*)/series", SearchForSeries);    
-      Register(root, "studies/([^/]*)/series/([^/]*)", RetrieveDicomSeries);
-      Register(root, "studies/([^/]*)/series/([^/]*)/instances", SearchForInstances);    
-      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)", RetrieveDicomInstance);
-      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/bulk/(.*)", RetrieveBulkData);
-      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/metadata", RetrieveInstanceMetadata);
-      Register(root, "studies/([^/]*)/series/([^/]*)/metadata", RetrieveSeriesMetadata);
-      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/frames/([^/]*)", RetrieveFrames);
+      Register(root, "instances", Protect<SearchForInstances>);
+      Register(root, "series", Protect<SearchForSeries>);    
+      Register(root, "studies", Protect<SwitchStudies>);
+      Register(root, "studies/([^/]*)", Protect<SwitchStudy>);
+      Register(root, "studies/([^/]*)/instances", Protect<SearchForInstances>);    
+      Register(root, "studies/([^/]*)/metadata", Protect<RetrieveStudyMetadata>);
+      Register(root, "studies/([^/]*)/series", Protect<SearchForSeries>);    
+      Register(root, "studies/([^/]*)/series/([^/]*)", Protect<RetrieveDicomSeries>);
+      Register(root, "studies/([^/]*)/series/([^/]*)/instances", Protect<SearchForInstances>);    
+      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)", Protect<RetrieveDicomInstance>);
+      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/bulk/(.*)", Protect<RetrieveBulkData>);
+      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/metadata", Protect<RetrieveInstanceMetadata>);
+      Register(root, "studies/([^/]*)/series/([^/]*)/metadata", Protect<RetrieveSeriesMetadata>);
+      Register(root, "studies/([^/]*)/series/([^/]*)/instances/([^/]*)/frames/([^/]*)", Protect<RetrieveFrames>);
     }
     else
     {
--- a/Plugin/QidoRs.cpp	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/QidoRs.cpp	Wed Dec 09 10:05:51 2015 +0100
@@ -465,34 +465,16 @@
                                         const char* url,
                                         const OrthancPluginHttpRequest* request)
 {
-  try
+  if (request->method != OrthancPluginHttpMethod_Get)
   {
-    if (request->method != OrthancPluginHttpMethod_Get)
-    {
-      OrthancPluginSendMethodNotAllowed(context_, output, "GET");
-      return OrthancPluginErrorCode_Success;
-    }
-
-    ModuleMatcher matcher(request);
-    ApplyMatcher(output, request, matcher, QueryLevel_Study);
-
+    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (boost::bad_lexical_cast& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  ModuleMatcher matcher(request);
+  ApplyMatcher(output, request, matcher, QueryLevel_Study);
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -500,41 +482,23 @@
                                        const char* url,
                                        const OrthancPluginHttpRequest* request)
 {
-  try
+  if (request->method != OrthancPluginHttpMethod_Get)
   {
-    if (request->method != OrthancPluginHttpMethod_Get)
-    {
-      OrthancPluginSendMethodNotAllowed(context_, output, "GET");
-      return OrthancPluginErrorCode_Success;
-    }
-
-    ModuleMatcher matcher(request);
-
-    if (request->groupsCount == 1)
-    {
-      // The "StudyInstanceUID" is provided by the regular expression
-      matcher.AddFilter(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, request->groups[0]);
-    }
-
-    ApplyMatcher(output, request, matcher, QueryLevel_Series);
-
+    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (boost::bad_lexical_cast& e)
+
+  ModuleMatcher matcher(request);
+
+  if (request->groupsCount == 1)
   {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
+    // The "StudyInstanceUID" is provided by the regular expression
+    matcher.AddFilter(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, request->groups[0]);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  ApplyMatcher(output, request, matcher, QueryLevel_Series);
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -542,45 +506,27 @@
                                           const char* url,
                                           const OrthancPluginHttpRequest* request)
 {
-  try
+  if (request->method != OrthancPluginHttpMethod_Get)
   {
-    if (request->method != OrthancPluginHttpMethod_Get)
-    {
-      OrthancPluginSendMethodNotAllowed(context_, output, "GET");
-      return OrthancPluginErrorCode_Success;
-    }
-
-    ModuleMatcher matcher(request);
-
-    if (request->groupsCount == 1 || request->groupsCount == 2)
-    {
-      // The "StudyInstanceUID" is provided by the regular expression
-      matcher.AddFilter(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, request->groups[0]);
-    }
-
-    if (request->groupsCount == 2)
-    {
-      // The "SeriesInstanceUID" is provided by the regular expression
-      matcher.AddFilter(OrthancPlugins::DICOM_TAG_SERIES_INSTANCE_UID, request->groups[1]);
-    }
-
-    ApplyMatcher(output, request, matcher, QueryLevel_Instance);
-
+    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (boost::bad_lexical_cast& e)
+
+  ModuleMatcher matcher(request);
+
+  if (request->groupsCount == 1 || request->groupsCount == 2)
   {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
+    // The "StudyInstanceUID" is provided by the regular expression
+    matcher.AddFilter(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, request->groups[0]);
   }
-  catch (std::runtime_error& e)
+
+  if (request->groupsCount == 2)
   {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
+    // The "SeriesInstanceUID" is provided by the regular expression
+    matcher.AddFilter(OrthancPlugins::DICOM_TAG_SERIES_INSTANCE_UID, request->groups[1]);
   }
+
+  ApplyMatcher(output, request, matcher, QueryLevel_Instance);
+
+  return OrthancPluginErrorCode_Success;
 }
--- a/Plugin/StowRs.cpp	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/StowRs.cpp	Wed Dec 09 10:05:51 2015 +0100
@@ -88,157 +88,144 @@
                                     const char* url,
                                     const OrthancPluginHttpRequest* request)
 {
-  try
-  {
-    const std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(configuration_, request);
+  const std::string wadoBase = OrthancPlugins::Configuration::GetBaseUrl(configuration_, request);
 
 
-    if (request->method != OrthancPluginHttpMethod_Post)
-    {
-      OrthancPluginSendMethodNotAllowed(context_, output, "POST");
-      return OrthancPluginErrorCode_Success;
-    }
+  if (request->method != OrthancPluginHttpMethod_Post)
+  {
+    OrthancPluginSendMethodNotAllowed(context_, output, "POST");
+    return OrthancPluginErrorCode_Success;
+  }
 
-    std::string expectedStudy;
-    if (request->groupsCount == 1)
-    {
-      expectedStudy = request->groups[0];
-    }
+  std::string expectedStudy;
+  if (request->groupsCount == 1)
+  {
+    expectedStudy = request->groups[0];
+  }
 
-    if (expectedStudy.empty())
-    {
-      OrthancPluginLogInfo(context_, "STOW-RS request without study");
-    }
-    else
-    {
-      std::string s = "STOW-RS request restricted to study UID " + expectedStudy;
-      OrthancPluginLogInfo(context_, s.c_str());
-    }
+  if (expectedStudy.empty())
+  {
+    OrthancPluginLogInfo(context_, "STOW-RS request without study");
+  }
+  else
+  {
+    std::string s = "STOW-RS request restricted to study UID " + expectedStudy;
+    OrthancPluginLogInfo(context_, s.c_str());
+  }
 
-    bool isXml = IsXmlExpected(request);
+  bool isXml = IsXmlExpected(request);
 
-    std::string header;
-    if (!OrthancPlugins::LookupHttpHeader(header, request, "content-type"))
-    {
-      OrthancPluginLogError(context_, "No content type in the HTTP header of a STOW-RS request");
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;    
-    }
+  std::string header;
+  if (!OrthancPlugins::LookupHttpHeader(header, request, "content-type"))
+  {
+    OrthancPluginLogError(context_, "No content type in the HTTP header of a STOW-RS request");
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
+    return OrthancPluginErrorCode_Success;    
+  }
 
-    std::string application;
-    std::map<std::string, std::string> attributes;
-    OrthancPlugins::ParseContentType(application, attributes, header);
+  std::string application;
+  std::map<std::string, std::string> attributes;
+  OrthancPlugins::ParseContentType(application, attributes, header);
 
-    if (application != "multipart/related" ||
-        attributes.find("type") == attributes.end() ||
-        attributes.find("boundary") == attributes.end())
-    {
-      std::string s = "Unable to parse the content type of a STOW-RS request (" + application + ")";
-      OrthancPluginLogError(context_, s.c_str());
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
+  if (application != "multipart/related" ||
+      attributes.find("type") == attributes.end() ||
+      attributes.find("boundary") == attributes.end())
+  {
+    std::string s = "Unable to parse the content type of a STOW-RS request (" + application + ")";
+    OrthancPluginLogError(context_, s.c_str());
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
+    return OrthancPluginErrorCode_Success;
+  }
 
 
-    std::string boundary = attributes["boundary"]; 
+  std::string boundary = attributes["boundary"]; 
+
+  if (attributes["type"] != "application/dicom")
+  {
+    OrthancPluginLogError(context_, "The STOW-RS plugin currently only supports application/dicom");
+    OrthancPluginSendHttpStatusCode(context_, output, 415 /* Unsupported media type */);
+    return OrthancPluginErrorCode_Success;
+  }
+
+
 
-    if (attributes["type"] != "application/dicom")
+  bool isFirst = true;
+  gdcm::DataSet result;
+  gdcm::SmartPointer<gdcm::SequenceOfItems> success = new gdcm::SequenceOfItems();
+  gdcm::SmartPointer<gdcm::SequenceOfItems> failed = new gdcm::SequenceOfItems();
+  
+  std::vector<OrthancPlugins::MultipartItem> items;
+  OrthancPlugins::ParseMultipartBody(items, request->body, request->bodySize, boundary);
+  for (size_t i = 0; i < items.size(); i++)
+  {
+    if (!items[i].contentType_.empty() &&
+        items[i].contentType_ != "application/dicom")
     {
-      OrthancPluginLogError(context_, "The STOW-RS plugin currently only supports application/dicom");
+      std::string s = "The STOW-RS request contains a part that is not application/dicom (it is: \"" + items[i].contentType_ + "\")";
+      OrthancPluginLogError(context_, s.c_str());
       OrthancPluginSendHttpStatusCode(context_, output, 415 /* Unsupported media type */);
       return OrthancPluginErrorCode_Success;
     }
 
+    OrthancPlugins::ParsedDicomFile dicom(items[i]);
 
+    std::string studyInstanceUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, "", true);
+    std::string sopClassUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SOP_CLASS_UID, "", true);
+    std::string sopInstanceUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SOP_INSTANCE_UID, "", true);
+
+    gdcm::Item item;
+    item.SetVLToUndefined();
+    gdcm::DataSet &status = item.GetNestedDataSet();
+
+    SetTag(status, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_CLASS_UID, gdcm::VR::UI, sopClassUid);
+    SetTag(status, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_INSTANCE_UID, gdcm::VR::UI, sopInstanceUid);
 
-    bool isFirst = true;
-    gdcm::DataSet result;
-    gdcm::SmartPointer<gdcm::SequenceOfItems> success = new gdcm::SequenceOfItems();
-    gdcm::SmartPointer<gdcm::SequenceOfItems> failed = new gdcm::SequenceOfItems();
-  
-    std::vector<OrthancPlugins::MultipartItem> items;
-    OrthancPlugins::ParseMultipartBody(items, request->body, request->bodySize, boundary);
-    for (size_t i = 0; i < items.size(); i++)
+    if (!expectedStudy.empty() &&
+        studyInstanceUid != expectedStudy)
     {
-      if (!items[i].contentType_.empty() &&
-          items[i].contentType_ != "application/dicom")
+      std::string s = ("STOW-RS request restricted to study [" + expectedStudy + 
+                       "]: Ignoring instance from study [" + studyInstanceUid + "]");
+      OrthancPluginLogInfo(context_, s.c_str());
+
+      SetTag(status, OrthancPlugins::DICOM_TAG_WARNING_REASON, gdcm::VR::US, "B006");  // Elements discarded
+      success->AddItem(item);      
+    }
+    else
+    {
+      if (isFirst)
       {
-        std::string s = "The STOW-RS request contains a part that is not application/dicom (it is: \"" + items[i].contentType_ + "\")";
-        OrthancPluginLogError(context_, s.c_str());
-        OrthancPluginSendHttpStatusCode(context_, output, 415 /* Unsupported media type */);
-        return OrthancPluginErrorCode_Success;
+        std::string url = wadoBase + "studies/" + studyInstanceUid;
+        SetTag(result, OrthancPlugins::DICOM_TAG_RETRIEVE_URL, gdcm::VR::UT, url);
+        isFirst = false;
       }
 
-      OrthancPlugins::ParsedDicomFile dicom(items[i]);
-
-      std::string studyInstanceUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_STUDY_INSTANCE_UID, "", true);
-      std::string sopClassUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SOP_CLASS_UID, "", true);
-      std::string sopInstanceUid = dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SOP_INSTANCE_UID, "", true);
-
-      gdcm::Item item;
-      item.SetVLToUndefined();
-      gdcm::DataSet &status = item.GetNestedDataSet();
+      OrthancPluginMemoryBuffer result;
+      bool ok = OrthancPluginRestApiPost(context_, &result, "/instances", items[i].data_, items[i].size_) == 0;
+      OrthancPluginFreeMemoryBuffer(context_, &result);
 
-      SetTag(status, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_CLASS_UID, gdcm::VR::UI, sopClassUid);
-      SetTag(status, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_INSTANCE_UID, gdcm::VR::UI, sopInstanceUid);
-
-      if (!expectedStudy.empty() &&
-          studyInstanceUid != expectedStudy)
+      if (ok)
       {
-        std::string s = ("STOW-RS request restricted to study [" + expectedStudy + 
-                         "]: Ignoring instance from study [" + studyInstanceUid + "]");
-        OrthancPluginLogInfo(context_, s.c_str());
+        std::string url = (wadoBase + 
+                           "studies/" + studyInstanceUid +
+                           "/series/" + dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SERIES_INSTANCE_UID, "", true) +
+                           "/instances/" + sopInstanceUid);
 
-        SetTag(status, OrthancPlugins::DICOM_TAG_WARNING_REASON, gdcm::VR::US, "B006");  // Elements discarded
-        success->AddItem(item);      
+        SetTag(status, OrthancPlugins::DICOM_TAG_RETRIEVE_URL, gdcm::VR::UT, url);
+        success->AddItem(item);
       }
       else
       {
-        if (isFirst)
-        {
-          std::string url = wadoBase + "studies/" + studyInstanceUid;
-          SetTag(result, OrthancPlugins::DICOM_TAG_RETRIEVE_URL, gdcm::VR::UT, url);
-          isFirst = false;
-        }
-
-        OrthancPluginMemoryBuffer result;
-        bool ok = OrthancPluginRestApiPost(context_, &result, "/instances", items[i].data_, items[i].size_) == 0;
-        OrthancPluginFreeMemoryBuffer(context_, &result);
-
-        if (ok)
-        {
-          std::string url = (wadoBase + 
-                             "studies/" + studyInstanceUid +
-                             "/series/" + dicom.GetTagWithDefault(OrthancPlugins::DICOM_TAG_SERIES_INSTANCE_UID, "", true) +
-                             "/instances/" + sopInstanceUid);
-
-          SetTag(status, OrthancPlugins::DICOM_TAG_RETRIEVE_URL, gdcm::VR::UT, url);
-          success->AddItem(item);
-        }
-        else
-        {
-          OrthancPluginLogError(context_, "Orthanc was unable to store instance through STOW-RS request");
-          SetTag(status, OrthancPlugins::DICOM_TAG_FAILURE_REASON, gdcm::VR::US, "0110");  // Processing failure
-          failed->AddItem(item);
-        }
+        OrthancPluginLogError(context_, "Orthanc was unable to store instance through STOW-RS request");
+        SetTag(status, OrthancPlugins::DICOM_TAG_FAILURE_REASON, gdcm::VR::US, "0110");  // Processing failure
+        failed->AddItem(item);
       }
     }
+  }
 
-    SetSequenceTag(result, OrthancPlugins::DICOM_TAG_FAILED_SOP_SEQUENCE, failed);
-    SetSequenceTag(result, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_SEQUENCE, success);
-
-    OrthancPlugins::AnswerDicom(context_, output, wadoBase, *dictionary_, result, isXml, false);
+  SetSequenceTag(result, OrthancPlugins::DICOM_TAG_FAILED_SOP_SEQUENCE, failed);
+  SetSequenceTag(result, OrthancPlugins::DICOM_TAG_REFERENCED_SOP_SEQUENCE, success);
 
-    return OrthancPluginErrorCode_Success;
-  }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+  OrthancPlugins::AnswerDicom(context_, output, wadoBase, *dictionary_, result, isXml, false);
+
+  return OrthancPluginErrorCode_Success;
 }
--- a/Plugin/Wado.cpp	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/Wado.cpp	Wed Dec 09 10:05:51 2015 +0100
@@ -237,55 +237,38 @@
                                     const char* url,
                                     const OrthancPluginHttpRequest* request)
 {
-  try
+  if (request->method != OrthancPluginHttpMethod_Get)
   {
-    if (request->method != OrthancPluginHttpMethod_Get)
-    {
-      OrthancPluginSendMethodNotAllowed(context_, output, "GET");
-      return OrthancPluginErrorCode_Plugin;
-    }
-
-    std::string instance;
-    std::string contentType = "image/jpg";  // By default, JPEG image will be returned
-    if (!LocateInstance(instance, contentType, request))
-    {
-#if HAS_ERROR_CODE == 1
-      return OrthancPluginErrorCode_UnknownResource;
-#else
-      return OrthancPluginErrorCode_Plugin;
-#endif
-    }
-
-    if (contentType == "application/dicom")
-    {
-      return AnswerDicom(output, instance);
-    }
-    else if (contentType == "image/png")
-    {
-      return AnswerPngPreview(output, instance);
-    }
-    else if (contentType == "image/jpeg" ||
-             contentType == "image/jpg")
-    {
-      return AnswerJpegPreview(output, instance);
-    }
-    else
-    {
-      std::string msg = "WADO: Unsupported content type: \"" + contentType + "\"";
-      OrthancPluginLogError(context_, msg.c_str());
-      return OrthancPluginErrorCode_Plugin;
-    }
-
-    return OrthancPluginErrorCode_Success;
-  }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
+    OrthancPluginSendMethodNotAllowed(context_, output, "GET");
     return OrthancPluginErrorCode_Plugin;
   }
-  catch (std::runtime_error& e)
+
+  std::string instance;
+  std::string contentType = "image/jpg";  // By default, JPEG image will be returned
+  if (!LocateInstance(instance, contentType, request))
+  {
+    return OrthancPluginErrorCode_UnknownResource;
+  }
+
+  if (contentType == "application/dicom")
   {
-    OrthancPluginLogError(context_, e.what());
+    return AnswerDicom(output, instance);
+  }
+  else if (contentType == "image/png")
+  {
+    return AnswerPngPreview(output, instance);
+  }
+  else if (contentType == "image/jpeg" ||
+           contentType == "image/jpg")
+  {
+    return AnswerJpegPreview(output, instance);
+  }
+  else
+  {
+    std::string msg = "WADO: Unsupported content type: \"" + contentType + "\"";
+    OrthancPluginLogError(context_, msg.c_str());
     return OrthancPluginErrorCode_Plugin;
   }
+
+  return OrthancPluginErrorCode_Success;
 }
--- a/Plugin/WadoRs.cpp	Tue Dec 08 20:23:27 2015 +0100
+++ b/Plugin/WadoRs.cpp	Wed Dec 09 10:05:51 2015 +0100
@@ -382,32 +382,19 @@
                                           const char* url,
                                           const OrthancPluginHttpRequest* request)
 {
-  try
+  if (!AcceptMultipartDicom(request))
   {
-    if (!AcceptMultipartDicom(request))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateStudy(output, uri, request))
-    {
-      AnswerListOfDicomInstances(output, uri);
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateStudy(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    AnswerListOfDicomInstances(output, uri);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -415,32 +402,19 @@
                                            const char* url,
                                            const OrthancPluginHttpRequest* request)
 {
-  try
+  if (!AcceptMultipartDicom(request))
   {
-    if (!AcceptMultipartDicom(request))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateSeries(output, uri, request))
-    {
-      AnswerListOfDicomInstances(output, uri);
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateSeries(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    AnswerListOfDicomInstances(output, uri);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -449,42 +423,29 @@
                                              const char* url,
                                              const OrthancPluginHttpRequest* request)
 {
-  try
+  if (!AcceptMultipartDicom(request))
   {
-    if (!AcceptMultipartDicom(request))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateInstance(output, uri, request))
-    {
-      if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/dicom"))
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-  
-      std::string dicom;
-      if (OrthancPlugins::RestApiGetString(dicom, context_, uri + "/file") &&
-          OrthancPluginSendMultipartItem(context_, output, dicom.c_str(), dicom.size()) != 0)
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateInstance(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/dicom"))
+    {
+      return OrthancPluginErrorCode_Plugin;
+    }
+  
+    std::string dicom;
+    if (OrthancPlugins::RestApiGetString(dicom, context_, uri + "/file") &&
+        OrthancPluginSendMultipartItem(context_, output, dicom.c_str(), dicom.size()) != 0)
+    {
+      return OrthancPluginErrorCode_Plugin;
+    }
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -493,33 +454,20 @@
                                              const char* url,
                                              const OrthancPluginHttpRequest* request)
 {
-  try
+  bool isXml;
+  if (!AcceptMetadata(request, isXml))
   {
-    bool isXml;
-    if (!AcceptMetadata(request, isXml))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateStudy(output, uri, request))
-    {
-      AnswerMetadata(output, request, uri, false, isXml);
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateStudy(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    AnswerMetadata(output, request, uri, false, isXml);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -527,33 +475,20 @@
                                               const char* url,
                                               const OrthancPluginHttpRequest* request)
 {
-  try
+  bool isXml;
+  if (!AcceptMetadata(request, isXml))
   {
-    bool isXml;
-    if (!AcceptMetadata(request, isXml))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateSeries(output, uri, request))
-    {
-      AnswerMetadata(output, request, uri, false, isXml);
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateSeries(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    AnswerMetadata(output, request, uri, false, isXml);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -561,33 +496,20 @@
                                                 const char* url,
                                                 const OrthancPluginHttpRequest* request)
 {
-  try
+  bool isXml;
+  if (!AcceptMetadata(request, isXml))
   {
-    bool isXml;
-    if (!AcceptMetadata(request, isXml))
-    {
-      OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri;
-    if (LocateInstance(output, uri, request))
-    {
-      AnswerMetadata(output, request, uri, true, isXml);
-    }
-
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
     return OrthancPluginErrorCode_Success;
   }
-  catch (Orthanc::OrthancException& e)
+
+  std::string uri;
+  if (LocateInstance(output, uri, request))
   {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
+    AnswerMetadata(output, request, uri, true, isXml);
   }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -666,51 +588,38 @@
                                         const char* url,
                                         const OrthancPluginHttpRequest* request)
 {
-  try
+  if (!AcceptBulkData(request))
+  {
+    OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
+    return OrthancPluginErrorCode_Success;
+  }
+
+  std::string uri, content;
+  if (LocateInstance(output, uri, request) &&
+      OrthancPlugins::RestApiGetString(content, context_, uri + "/file"))
   {
-    if (!AcceptBulkData(request))
+    OrthancPlugins::ParsedDicomFile dicom(content);
+
+    std::vector<std::string> path;
+    Orthanc::Toolbox::TokenizeString(path, request->groups[3], '/');
+      
+    std::string result;
+    if (path.size() % 2 == 1 &&
+        ExploreBulkData(result, path, 0, dicom.GetDataSet()))
+    {
+      if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/octet-stream") != 0 ||
+          OrthancPluginSendMultipartItem(context_, output, result.c_str(), result.size()) != 0)
+      {
+        return OrthancPluginErrorCode_Plugin;
+      }
+    }
+    else
     {
       OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      return OrthancPluginErrorCode_Success;
-    }
-
-    std::string uri, content;
-    if (LocateInstance(output, uri, request) &&
-        OrthancPlugins::RestApiGetString(content, context_, uri + "/file"))
-    {
-      OrthancPlugins::ParsedDicomFile dicom(content);
+    }      
+  }
 
-      std::vector<std::string> path;
-      Orthanc::Toolbox::TokenizeString(path, request->groups[3], '/');
-      
-      std::string result;
-      if (path.size() % 2 == 1 &&
-          ExploreBulkData(result, path, 0, dicom.GetDataSet()))
-      {
-        if (OrthancPluginStartMultipartAnswer(context_, output, "related", "application/octet-stream") != 0 ||
-            OrthancPluginSendMultipartItem(context_, output, result.c_str(), result.size()) != 0)
-        {
-          return OrthancPluginErrorCode_Plugin;
-        }
-      }
-      else
-      {
-        OrthancPluginSendHttpStatusCode(context_, output, 400 /* Bad request */);
-      }      
-    }
-
-    return OrthancPluginErrorCode_Success;
-  }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+  return OrthancPluginErrorCode_Success;
 }
 
 
@@ -723,6 +632,10 @@
 #include <gdcmJPEG2000Codec.h>
 
 
+
+
+
+
 OrthancPluginErrorCode RetrieveFrames(OrthancPluginRestOutput* output,
                                       const char* url,
                                       const OrthancPluginHttpRequest* request)
@@ -731,54 +644,45 @@
 
   // http://gdcm.sourceforge.net/html/CompressLossyJPEG_8cs-example.html
 
-  try
+  std::string uri, content;
+  if (LocateInstance(output, uri, request) &&
+      OrthancPlugins::RestApiGetString(content, context_, uri + "/file"))
   {
-    std::string uri, content;
-    if (LocateInstance(output, uri, request) &&
-        OrthancPlugins::RestApiGetString(content, context_, uri + "/file"))
-    {
-      printf("RetrieveFrames: [%s] [%s]\n", uri.c_str(), request->groups[3]);
+    printf("RetrieveFrames: [%s] [%s]\n", uri.c_str(), request->groups[3]);
 
-      gdcm::ImageChangeTransferSyntax change;
-      change.SetTransferSyntax(gdcm::TransferSyntax::JPEG2000Lossless);
+    gdcm::ImageChangeTransferSyntax change;
+    change.SetTransferSyntax(gdcm::TransferSyntax::JPEG2000Lossless);
 
-      gdcm::JPEG2000Codec codec;
-      if (!codec.CanCode(change.GetTransferSyntax()))
-      {
-        return OrthancPluginErrorCode_Plugin;
-      }
+    gdcm::JPEG2000Codec codec;
+    if (!codec.CanCode(change.GetTransferSyntax()))
+    {
+      return OrthancPluginErrorCode_Plugin;
+    }
 
-      //codec.SetLossless(true);
-      change.SetUserCodec(&codec);
+    //codec.SetLossless(true);
+    change.SetUserCodec(&codec);
 
-      std::stringstream stream(content);
-
-      gdcm::ImageReader reader;
-      reader.SetStream(stream);
-      printf("Read: %d\n", reader.Read());
+    std::stringstream stream(content);
 
-      change.SetInput(reader.GetImage());
-      printf("Change: %d\n", change.Change());
+    gdcm::ImageReader reader;
+    reader.SetStream(stream);
+    printf("Read: %d\n", reader.Read());
 
-      gdcm::ImageWriter writer;
-      writer.SetImage(change.GetOutput());
-      writer.SetFile(reader.GetFile());
-      
-      //gdcm::File output;
-      writer.SetFileName("/tmp/tutu.dcm");
-      printf("Write: %d\n", writer.Write());
-    }    
+    change.SetInput(reader.GetImage());
+    printf("Change: %d\n", change.Change());
 
-    return OrthancPluginErrorCode_Success;
-  }
-  catch (Orthanc::OrthancException& e)
-  {
-    OrthancPluginLogError(context_, e.What());
-    return OrthancPluginErrorCode_Plugin;
-  }
-  catch (std::runtime_error& e)
-  {
-    OrthancPluginLogError(context_, e.what());
-    return OrthancPluginErrorCode_Plugin;
-  }
+    gdcm::ImageWriter writer;
+    writer.SetImage(change.GetOutput());
+    writer.SetFile(reader.GetFile());
+      
+    std::stringstream ss;
+    writer.SetStream(ss);
+    printf("Write: %d\n", writer.Write());
+
+    gdcm::ImageReader reader2;
+    reader2.SetStream(ss);
+    printf("Read: %d\n", reader2.Read());
+  }    
+
+  return OrthancPluginErrorCode_Success;
 }