Skip to content

WADO-RS ignores the Accept header #60

Description

@thunfischtoast

Problem

The WADO-RS retrieve endpoints do not perform media type negotiation. The Accept header is only mined for the transfer-syntax parameter (service.rs extractor); the response media type is fixed (routes.rs). There is no 406 path anywhere in the codebase (grep -rn 406 src is empty).

DICOM PS3.18 Section 8.7.5 requires for the Retrieve transaction:

  • the Accept header field shall be present; a request without one shall be answered with 406 (Not Acceptable);
  • if the origin server cannot produce any acceptable media type, the response shall be 406;
  • an Accept mixing DICOM and Rendered media types shall be answered with 400 (Bad Request).

Instead, every request gets 200 with multipart/related; type="application/dicom", whatever it asked for. Clients cannot detect that their requested representation (e.g. single-part application/dicom, or application/dicom+json) is unsupported, but they get a multipart body their parser may not expect.

Reproduction

Using examples/simple-setup (verified against DICOM-RST/0.3.0-beta.5). Requires only curl and jq; the test instance is synthesized via Orthanc's API, no DICOM files needed.

cd examples/simple-setup && docker compose up -d

# Create a synthetic instance in Orthanc and build the WADO-RS URL from its UIDs:
ID=$(curl -s http://localhost:8042/tools/create-dicom \
  -d '{"Tags":{"PatientName":"ACCEPT^TEST","SOPClassUID":"1.2.840.10008.5.1.4.1.1.7"}}' | jq -r .ID)
URL=$(curl -s "http://localhost:8042/instances/$ID/tags?simplify" | jq -r \
  '"http://localhost:8080/aets/ORTHANC/studies/\(.StudyInstanceUID)/series/\(.SeriesInstanceUID)/instances/\(.SOPInstanceUID)"')

# 1) Unsupported media type (expected 406):
curl -sD- -o /dev/null -H 'Accept: application/dicom+json' "$URL"

# 2) No Accept header at all  (expected 406):
curl -sD- -o /dev/null -H 'Accept:' "$URL"

# 3) DICOM and Rendered media types mixed (expected 400):
curl -sD- -o /dev/null -H 'Accept: multipart/related; type="application/dicom", image/jpeg' "$URL"

All three return the identical response:

HTTP/1.1 200 OK
content-disposition: attachment; filename="1.2.276.0.7230010.3.1.2.447480576.1.1786095984.672056"
content-type: multipart/related; type="application/dicom"; boundary=boundary
vary: origin, access-control-request-method, access-control-request-headers
access-control-allow-origin: *
access-control-expose-headers: *
server: DICOM-RST/0.3.0-beta.5
transfer-encoding: chunked

The body is a real, successful multipart response (first part is a valid Part-10 instance), so this is not a downstream failure, negotiation simply never happens.

Request Expected (PS3.18 §8.7.5) Actual
Accept: application/dicom+json 406 200, multipart/related
no Accept header 406 200, multipart/related
DICOM + Rendered mix 400 200, multipart/related

See also: #59

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

service:wado-rsThis issue affects the WADO-RS service

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions