changeset 577:4e7ed606a9a4

improved multipart DICOM negotiation
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Jun 2023 11:13:26 +0200
parents 26f7f795e379
children a083f083f2ac
files Plugin/WadoRs.cpp
diffstat 1 files changed, 77 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/Plugin/WadoRs.cpp	Wed Jun 28 10:37:35 2023 +0200
+++ b/Plugin/WadoRs.cpp	Wed Jun 28 11:13:26 2023 +0200
@@ -63,6 +63,71 @@
 
 
 
+namespace
+{
+  class MultipartDicomNegotiation : public Orthanc::HttpContentNegociation::IHandler
+  {
+  private:
+    bool&                         transcode_;
+    Orthanc::DicomTransferSyntax& targetSyntax_;
+
+  public:
+    MultipartDicomNegotiation(
+      bool& transcode,
+      Orthanc::DicomTransferSyntax& targetSyntax /* set only if transcoding */) :
+      transcode_(transcode),
+      targetSyntax_(targetSyntax)
+    {
+    }
+
+    virtual void Handle(const std::string& type,
+                        const std::string& subtype,
+                        const Orthanc::HttpContentNegociation::Dictionary& parameters) ORTHANC_OVERRIDE
+    {
+      assert(type == "multipart" &&
+             subtype == "related");
+
+      Orthanc::HttpContentNegociation::Dictionary::const_iterator found = parameters.find("type");
+
+      if (found != parameters.end())
+      {
+        std::string s = found->second;
+        Orthanc::Toolbox::ToLowerCase(s);
+        if (s != "application/dicom")
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
+                                          "This WADO-RS plugin only supports application/dicom "
+                                          "return type for DICOM retrieval (" + found->second + ")");
+        }
+      }
+
+      found = parameters.find("transfer-syntax");
+      if (found != parameters.end())
+      {
+        /**
+         * The "*" case below is related to Google Healthcare API:
+         * https://groups.google.com/d/msg/orthanc-users/w1Ekrsc6-U8/T2a_DoQ5CwAJ
+         **/
+        if (found->second == "*")
+        {
+          transcode_ = false;
+        }
+        else
+        {
+          transcode_ = true;
+
+          if (!Orthanc::LookupTransferSyntax(targetSyntax_, found->second))
+          {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
+                                            "Unsupported transfer syntax in WADO-RS: " + found->second);
+          }
+        }
+      }
+    }
+  };
+}
+
+
 static void AcceptMultipartDicom(bool& transcode,
                                  Orthanc::DicomTransferSyntax& targetSyntax /* only if transcoding */,
                                  const OrthancPluginHttpRequest* request)
@@ -99,52 +164,17 @@
   {
     return;   // By default, return "multipart/related; type=application/dicom;"
   }
-
-  std::string application;
-  std::map<std::string, std::string> attributes;
-  OrthancPlugins::ParseContentType(application, attributes, accept);
-
-  if (application != "multipart/related" &&
-      application != "*/*")
+  else
   {
-    throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
-                                    "This WADO-RS plugin cannot generate the following content type: " + accept);
-  }
+    Orthanc::HttpContentNegociation negotiation;
 
-  if (attributes.find("type") != attributes.end())
-  {
-    std::string s = attributes["type"];
-    Orthanc::Toolbox::ToLowerCase(s);
-    if (s != "application/dicom")
+    MultipartDicomNegotiation dicom(transcode, targetSyntax);
+    negotiation.Register("multipart/related", dicom);
+
+    if (!negotiation.Apply(accept))
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
-                                      "This WADO-RS plugin only supports application/dicom "
-                                      "return type for DICOM retrieval (" + accept + ")");
-    }
-  }
-
-  static const char* const TRANSFER_SYNTAX = "transfer-syntax";
-
-  std::map<std::string, std::string>::const_iterator found = attributes.find(TRANSFER_SYNTAX);
-  if (found != attributes.end())
-  {
-    /**
-     * The "*" case below is related to Google Healthcare API:
-     * https://groups.google.com/d/msg/orthanc-users/w1Ekrsc6-U8/T2a_DoQ5CwAJ
-     **/
-    if (found->second == "*")
-    {
-      transcode = false;
-    }
-    else
-    {
-      transcode = true;
-
-      if (!Orthanc::LookupTransferSyntax(targetSyntax, found->second))
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRequest,
-                                        "Unsupported transfer syntax in WADO-RS: " + found->second);
-      }
+                                      "This WADO-RS plugin cannot generate the following content type: " + accept);
     }
   }
 }
@@ -227,16 +257,16 @@
   }
   else
   {
-    Orthanc::HttpContentNegociation negociation;
+    Orthanc::HttpContentNegociation negotiation;
 
     AcceptMetadataJson json;
-    negociation.Register("application/json", json);
-    negociation.Register("application/dicom+json", json);
+    negotiation.Register("application/json", json);
+    negotiation.Register("application/dicom+json", json);
 
     AcceptMetadataMultipart multipart(isXml);
-    negociation.Register("multipart/related", multipart);
+    negotiation.Register("multipart/related", multipart);
 
-    return negociation.Apply(accept);
+    return negotiation.Apply(accept);
   }
 }