Orthanc DicomWeb StowRS server request/ response compatibility

Hi @alainmazy ,

I have questions in the DicomWeb plugin code.
1/ Orthanc DicomWeb check header from the request

void StowServer::HandlePart(const Orthanc::MultipartStreamReader::HttpHeaders& headers,
                              const void* part,
                              size_t size)
  {
    std::string contentType;

    if (!Orthanc::MultipartStreamReader::GetMainContentType(contentType, headers) ||
        contentType != "application/dicom")
    {
      throw Orthanc::OrthancException(
        Orthanc::ErrorCode_UnsupportedMediaType,
        "The STOW-RS request contains a part that is not "
        "\"application/dicom\" (it is: \"" + contentType + "\")");
    }

    Json::Value dicom;
    bool ok = false;

The Content-Type should be : application/dicom. In the standard 6.6 STOW-RS Request/Response , it says that

The Transfer Syntax of each instance stored is encoded in Transfer Syntax UID (0002,0010) of the PS3.10 File Meta Information, and is not repeated in the Content-Type HTTP header as a parameter. If a transfer-syntax parameter is present and inconsistent with the PS3.10 File Meta Information, it will either be ignored or an error will be returned.

It does mean that transferSyntax could be adhered to the header Content-Type. In fact, dcm4chee sends Content-Type with transferSyntax

i.e Content-Type=application/dicom;transfer-syntax=1.2.840.10008.1.2.1, so Orthanc declines the request with error message:

I0422 14:01:28.382949           HTTP-0 HttpServer.cpp:1263] (http) POST /wado-rs/studies
I0422 14:01:28.383009           HTTP-0 OrthancPlugins.cpp:6366] (plugins) Delegating chunked HTTP request to plugin for URI: /wado-rs/studies
I0422 14:01:28.383032           HTTP-0 PluginsManager.cpp:162] (plugins) STOW-RS request without study
E0422 14:01:28.423970           HTTP-0 PluginsManager.cpp:154] Unsupported media type: The STOW-RS request contains a part that is not "application/dicom" (it is: "application/dicom;transfer-syntax=1.2.840.10008.1.2.1")

So is this possible to remove that validation in Orthanc DicomWeb code ? So Orthanc and Dcm4chee can work together ?

2/ Relating to to response from StowServer containing tag DICOM_TAG_FAILED_SOP_SEQUENCE. I think that if there is no error in processing stow message, then tag DICOM_TAG_FAILED_SOP_SEQUENCE should not be included in the response. Below is the code snippet from DicomWeb

void StowServer::Execute(OrthancPluginRestOutput* output)
  {
    assert(parser_.get() != NULL);
    parser_->CloseStream();

    result_[DICOM_TAG_FAILED_SOP_SEQUENCE.Format()] = failed_;
    result_[DICOM_TAG_REFERENCED_SOP_SEQUENCE.Format()] = success_;
    
    std::string answer;
    
    DicomWebFormatter::Apply(answer, context_, result_, xml_,
                             OrthancPluginDicomWebBinaryMode_Ignore, "");

    // http://dicom.nema.org/medical/dicom/current/output/html/part18.html#table_10.5.3-1
    uint16_t statusCode = 200;
    if (hasBadSyntax_)
    {
      statusCode = 400;
    }
    else if (hasConflict_)
    {
      statusCode = 409;
    }
    else if (failed_.size() > 0 && success_.size() == 0)  // only failed instances but not a conflict or bad syntax -> 400
    {
      statusCode = 400;
    }
    else if (failed_.size() > 0 && success_.size() > 0) // 202 = Accepted but some instances have failures
    {
      statusCode = 202;
    }

    if (statusCode == 200)
    {
      OrthancPluginAnswerBuffer(context_, output, answer.c_str(), answer.size(),
                                xml_ ? "application/dicom+xml" : "application/dicom+json");
    }
    else
    {
      // TODO: if statusCode is 202, the content will only be sent if HttpDescribeErrors is set to true -> would need OrthancPluginAnswerBuffer with an HttpStatusCode arg
      OrthancPluginSetHttpHeader(context_, output, "Content-Type", xml_ ? "application/dicom+xml" : "application/dicom+json");
      OrthancPluginSendHttpStatus(context_, output, statusCode, answer.c_str(), answer.size());  
    }
  };

In the standard 6.6 STOW-RS Request/Response, it says that

So could we remove this line :
result_[DICOM_TAG_FAILED_SOP_SEQUENCE.Format()] = failed_;
if there is no error in StowServer ?

I am asking this question because there is no compatibility between Orthanc and Dcm4chee. Dcm4chee check if there is a tag DICOM_TAG_FAILED_SOP_SEQUENCE in the response then it considers the response is error. Hence Dcm4chee cannot send stowrs message to Orthanc although Orthanc can handle and store stow message successfully.
Here is the code snippet from the dcm4chee arc light :

    private void onStowRsp(Attributes rsp) {
        if (rsp == null)
            return;

        if (rsp.contains(Tag.FailedSOPSequence)) {
            ctx.incrementFailed();
            return;
        }
        Attributes refSOP = rsp.getNestedDataset(Tag.ReferencedSOPSequence);
        if (refSOP.contains(Tag.WarningReason))
            ctx.incrementWarning();
        else
            ctx. ();
    }
1 Like

Hi @Christophe

First of all, thanks for this super detailed analysis ! It’s a real pleasure to implement a fix with these inputs :folded_hands:

So here’s the commit with the fixes and the new updated integration tests.

Could you validate that this works correctly with the mainline binaries ? I’m planning to release a new Dicom-Web plugin one of these days together with a new OHIF plugin.

Best regards,

Alain.

Hi @alainmazy ,

Thanks a lot for your quick implementation. I’ve pulled the latest code at orthanc-dicomweb: 1d3ba3e489d4 / and tested with dcm4chee. It works like a charm. Again, many thanks for your dedicated work.

2 Likes