Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Error: 406 Client Error: Not Acceptable for url #46

Closed
athanell opened this issue Mar 4, 2021 · 20 comments
Closed

HTTP Error: 406 Client Error: Not Acceptable for url #46

athanell opened this issue Mar 4, 2021 · 20 comments
Assignees
Labels
help wanted Extra attention is needed

Comments

@athanell
Copy link

athanell commented Mar 4, 2021

Hello,

I get a client error when connecting to an azure dicom webserver. I can see normally all the records and I can as well remove a selected series from the DICOMweb server through Slicer's extension. But when I try to "download and index" it I get:

DownloadSelectedSeries: Error in getting response from DICOMweb server.
HTTP Error:
406 Client Error: Not Acceptable for url: https://xxx-xxx.azurewebsites.net/studies/1.2.826.0.1.xxxxxx.x.xxx.x.x.xxxxxxxxxxx.xxxx.xxxx/series/1.2.826.0.1.xxxxxx.x.x.x.x.xxxx.xxx.xxxxx.xxxxxx/instances/1.2.826.0.1.xxxx.x.xxx.x.x.8xxxxx.xxx.xxxxxxxx.xxxxx

What could possibly go wrong?

OS: Win 10
Slicer version: 4.13.0-2021-03-03 r29745 / fca084e

Regards
Antonios

@pieper
Copy link
Member

pieper commented Mar 4, 2021

Do you have a way to replicate this on a public instance with anonymized data?

@pieper
Copy link
Member

pieper commented Mar 4, 2021

@athanell Thanks for the PM with more detail. Is it correct that no studies can be pulled from Microsoft's dicomweb server using Slicer's dicomweb browser? (i.e. it's not specific to this data). I haven't used their server before.

It looks like the underlying issue is the accept header options that Microsoft's server supports vs google and dcm4chee.

I can reproduce this with curl:

curl  "https://<public-server>/studies/1.2.<...>/series/1.2.<...>/instances/1.2<...>/frames/1"

The request headers are not acceptable

but

curl -H 'accept: multipart/related; type="application/octet-stream"'  "https://<public-server>/studies/1.2.<...>/series/1.2.<...>/instances/1.2<...>/frames/1"

Gives me a stream of data that looks valid (this is the header accept string that ohif uses).

Compare their conformance statements:

https://github.com/microsoft/dicom-server/blob/main/docs/resources/conformance-statement.md#retrieve-wado-rs

https://cloud.google.com/healthcare/docs/dicom#dicom_studyseriesinstances

@hackermd do you have experience with this?

MDN indicates that 406 codes are rarely helpful and maybe Microsoft should be more flexible, but it's also possible that a workaround in the client is preferred.

@lassoan might also have ideas.

@athanell
Copy link
Author

athanell commented Mar 4, 2021

@pieper yes I can verify that in order to pull data from Microsoft's dicomweb either with python or curl one needs to use the header "accept: multipart/related".

The same error came up with different datasets so I think that it is not a data-specific issue.

@hackermd
Copy link
Collaborator

hackermd commented Mar 5, 2021

Thanks @athanell for reporting the issue and @pieper for looking into it.

I am not sure I understand what the problem is and whether it is a problem with the library or the Slicer application.
The dicomweb_client.api.DICOMwebClient.retrieve_instance_frames() method sends requests with mulipart/related type="application/octet-stream" accept header (see here).

Do you have or could you create a debug log, i.e., configure the dicomweb_client logger with logging.DEBUG?

@hackermd hackermd added the help wanted Extra attention is needed label Mar 5, 2021
@lassoan
Copy link

lassoan commented Mar 6, 2021

The downloading in Slicer is fairly straightforward:

    instances = self.DICOMwebClient.search_for_instances(
      study_instance_uid=selectedStudy,
      series_instance_uid=selectedSeries
      )
    ...
    for instanceIndex, instance in enumerate(instances):
        ...
        retrievedInstance = self.DICOMwebClient.retrieve_instance(
          study_instance_uid=selectedStudy,
          series_instance_uid=selectedSeries,
          sop_instance_uid=sopInstanceUid)
        pydicom.filewriter.write_file(fileName, retrievedInstance)

(full source code)

Do you see anything suspicious in this?

@hackermd
Copy link
Collaborator

hackermd commented Mar 8, 2021

Thanks @lassoan!

Do you see anything suspicious in this?

No, looks good to me.

@hackermd
Copy link
Collaborator

hackermd commented Mar 8, 2021

@pieper @lassoan what version of dicomweb-client is used by this Slicer version?

The Microsoft dicom-server has an issue with the media type for the retrieve transaction. We updated the dicomweb-client after #41 (included in release 0.51.0.

@lassoan
Copy link

lassoan commented Mar 8, 2021

Latest DICOMWebBrowser extension installs 0.52.0:

@athanell Please check the version in your Slicer version by opening the Python console (Ctrl+3) and typing these:

>>> import dicomweb_client
>>> dicomweb_client.__version__
'0.52.0'

@athanell
Copy link
Author

athanell commented Mar 8, 2021

@lassoan yes I can verify that my version is the '0.52.0'

@hackermd
Copy link
Collaborator

hackermd commented Mar 8, 2021

Thanks @lassoan and @athanell for double-checking. It should not be the client version then. I have limited experience with the Microsoft dicom-server and will need to explore further.

@StevenBorg
Copy link

StevenBorg commented Mar 8, 2021

Hi! I'm just seeing this for the first time. Apologies for missing it earlier. I'm working on the Azure DICOM implementation. Let me run this error to ground. Thanks for all the context in the posts above. Although @hackermd let us know about the problem early on.

@hackermd
Copy link
Collaborator

hackermd commented Mar 8, 2021

Thanks @StevenBorg! We updated the dicomweb-client in version 0.51.0 such that it tolerates a response with content-type application/dicom or multipart/related; type="application/dicom" (see here). However, the client still includes the Accept: multipart/related; type="application/dicom" header in the request (see here). Technically, we should also include application/dicom in the accept header field, but were reluctant to do that because it's not compliant with the standard and may cause issues with other origin servers.

@athanell
Copy link
Author

Hello @pieper . I can replicate this error using Slicer's sample head CT on the server http://dicomweb.azurewebsites.net/ found in https://github.com/DICOMcloud/DICOMcloud

@pieper
Copy link
Member

pieper commented Mar 19, 2021

Thanks @athanell - let's see what @hackermd thinks when he gets back. I know he's reluctant to have the client support non-standard behavior and may be more inclined to work with the server developers for better compliance.

@hackermd
Copy link
Collaborator

Thanks for performing the additional tests @athanell! As @pieper pointed out, we are generally reluctant to support non-standard behavior. However, I've also come to painfully realize that sometimes there is not much one can do but work around a compliance issue. We should thus find a way to unblock users while working with the server implementer on resolving compliance issues.

@agharwal recently introduced a permissive flag for the constructor(s) of the dicomweb_client.uri.URI class (see PR #49) to relax enforcement of standard compliance. I wonder whether we want to extend this logic to the dicomweb_client.api.DICOMwebClient class?

@pieper @ntenenz what do you think about that?

@pieper
Copy link
Member

pieper commented Mar 30, 2021

From an application perspective (e.g. to a user of Slicer's DICOMwebBrowser extension) we would be looking for ways to make the code "just work" as often as possible without needing to know in advance that we wanted to be permissive or not. So I might expect the default behavior to be permissive. Unfortunately the end user often doesn't control the server, or even if they administer the server they don't have the ability to fix non-compliance. So they are relying on the application to handle as much as possible, meaning that the application developer wants to rely on the library developer to handle as much as possible. Unless it impacts performance or some other important thing the user probably doesn't care that the server is not compliant.

Perhaps the library could provide a way to audit servers for compliance (something like dciodvfy does for instances). This would give a basis for helping server developers to improve compliance.

@delton137
Copy link

I have the same issue. I pinpointed the issue arising going from 0.55.0 to 0.55.1 (and all following versions).

My solution is to use 0.55.0 for now.

Here's my code:

from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient(url=url)

 pydicom_dataset = client.retrieve_instance(
                    study_instance_uid=study_uid,
                    series_instance_uid=series_uid,
                    sop_instance_uid=object_uid,
                     )

The error is:

406 Client Error: Not Acceptable for url: http://......../studies/........../series/............../instances/.............

Note I'm running into this when trying to pull from an MGB VNA. I can provide more details on a private channel if desired. My email is delton at mgh . harvard

@hackermd
Copy link
Collaborator

In version 0.55.1, changes were made related to the handling of media types (see #63). These changes were not intended to be break anything, but the following change may lead to a change in server behavior (although it shouldn't from the perspective of the standard):
8ea25c5#diff-437b51b3f115cd02de5408a04dedfcc86f4110edec2a79f7f28ac96d88d06184R2664-R2665

@delton137 could please try setting the media_types=('application/dicom', ) explicitly and see whether that fixes things?

@delton137
Copy link

@hackermd using media_types=('application/dicom', ) in client.retrieve_instance() fixes the issue for me! Thanks - I can use the latest version now!

@hackermd
Copy link
Collaborator

@delton137 That is an indication that the archive has standard compliance issues. It appears it does not understand/handle the transfer-syntax part of the Accept header field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

6 participants