Skip to content

fix(DicomWebDataSource): set correct cross-service URLs on DICOMweb clients#6009

Open
galenzo17 wants to merge 5 commits into
OHIF:masterfrom
galenzo17:fix/dicomweb-cross-service-urls
Open

fix(DicomWebDataSource): set correct cross-service URLs on DICOMweb clients#6009
galenzo17 wants to merge 5 commits into
OHIF:masterfrom
galenzo17:fix/dicomweb-cross-service-urls

Conversation

@galenzo17
Copy link
Copy Markdown

@galenzo17 galenzo17 commented May 9, 2026

Summary

  • After client construction, assigns the correct cross-service URLs (wadoURL, qidoURL, stowURL) on each DICOMweb client so requests are routed to the right endpoint when qidoRoot and wadoRoot differ (e.g. /qidors/ vs /wadors/)
  • Adds optional stowRoot config field for deployments with a separate STOW endpoint
  • Adds unit tests covering cross-service URL assignment, explicit stowRoot, same-root (no-op), and stowRoot fallback scenarios

Closes #5820

Test plan

  • Cross-service URLs are correctly assigned when qidoRoot and wadoRoot differ
  • Explicit stowRoot is used when provided
  • Backward-compatible: no-op when qidoRoot === wadoRoot
  • stowURL defaults to wadoRoot when stowRoot is omitted

Greptile Summary

This PR extracts a new applyServiceUrls utility that cross-assigns wadoURL, qidoURL, and stowURL on each DICOMweb client after construction, fixing routing bugs when qidoRoot and wadoRoot differ. It also adds an optional stowRoot config field for deployments with a dedicated STOW endpoint.

  • applyServiceUrls.ts: three guarded blocks handle all root combinations — wadoRoot-only updates qidoClient, qidoRoot-only updates wadoClient, and an independent stowRoot block ensures both clients receive the explicit STOW URL even when qidoRoot is absent (the edge case flagged in prior review rounds).
  • index.ts: minimal integration — adds stowRoot to DicomWebConfig and calls applyServiceUrls immediately after both clients are constructed in initialize().
  • applyServiceUrls.test.ts: directly imports the utility and covers all six scenarios including the stowRoot-without-qidoRoot edge case.

Confidence Score: 5/5

Safe to merge — the cross-service URL assignment is correct across all root combinations, the ?? operator prevents silent fallback on empty-string inputs, and the third block correctly handles the stowRoot-without-qidoRoot case that caused a silent no-op in earlier iterations.

All issues raised in prior review rounds (falsy || check, unconditional undefined assignment, wadoClient.stowURL not updated when qidoRoot is absent) are resolved. The three-block structure is logically complete and all six test scenarios, including the previously uncovered edge case, pass.

No files require special attention.

Important Files Changed

Filename Overview
extensions/default/src/DicomWebDataSource/utils/applyServiceUrls.ts New utility function that cross-assigns service URLs on DICOMweb clients; three-block structure correctly handles all combinations of root presence/absence including the stowRoot-without-qidoRoot edge case flagged in prior review.
extensions/default/src/DicomWebDataSource/utils/applyServiceUrls.test.ts Proper unit tests directly importing the extracted utility; covers cross-service diff, explicit stowRoot, same-root, stowRoot fallback, qidoRoot-only, and stowRoot-without-qidoRoot scenarios.
extensions/default/src/DicomWebDataSource/index.ts Adds stowRoot to DicomWebConfig type and calls applyServiceUrls immediately after both clients are constructed in initialize(); integration is minimal and correct.

Reviews (6): Last reviewed commit: "fix(DicomWebDataSource): ensure explicit..." | Re-trigger Greptile

@netlify
Copy link
Copy Markdown

netlify Bot commented May 9, 2026

Deploy Preview for ohif-dev failed. Why did it fail? →

Name Link
🔨 Latest commit 6a487ef
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/6a11ee3386f2e80008798802

Comment on lines +27 to +42
* Applies the URL fix from index.ts lines ~211-219.
* Extracted here to test in isolation.
*/
function applyServiceUrls(
qidoClient: MockDICOMwebClient,
wadoClient: MockDICOMwebClient,
config: { qidoRoot: string; wadoRoot: string; stowRoot?: string }
) {
const effectiveStowRoot = config.stowRoot || config.wadoRoot;

qidoClient.wadoURL = config.wadoRoot;
qidoClient.stowURL = effectiveStowRoot;

wadoClient.qidoURL = config.qidoRoot;
wadoClient.stowURL = effectiveStowRoot;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Test logic decoupled from production code

applyServiceUrls is a hand-copied extract of the assignment block in index.ts. If the production logic changes (e.g., a guard is added, a URL property is renamed, or a new client is introduced), these tests will continue to pass while the real behavior regresses silently. The tests should import and exercise the actual createDicomWebApi initializer (or at minimum import a shared utility), not duplicate its logic inline.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/default/src/DicomWebDataSource/index.test.ts
Line: 27-42

Comment:
**Test logic decoupled from production code**

`applyServiceUrls` is a hand-copied extract of the assignment block in `index.ts`. If the production logic changes (e.g., a guard is added, a URL property is renamed, or a new client is introduced), these tests will continue to pass while the real behavior regresses silently. The tests should import and exercise the actual `createDicomWebApi` initializer (or at minimum import a shared utility), not duplicate its logic inline.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread extensions/default/src/DicomWebDataSource/index.ts Outdated
…lients

The dicomweb-client library sets qidoURL, wadoURL, and stowURL all to
the same base url when no prefixes are provided. This causes requests
to be routed to the wrong endpoint when qidoRoot and wadoRoot differ
(e.g. /qidors/ vs /wadors/).

Extract applyServiceUrls into a shared utility so the production code
and tests exercise the same function. After constructing the clients,
call applyServiceUrls to assign the correct cross-service URLs. Also
adds an optional stowRoot config field for deployments with a separate
STOW endpoint.

Closes OHIF#5820

Signed-off-by: Agustin Bereciartua <bereciartua.agustin@gmail.com>
@galenzo17 galenzo17 force-pushed the fix/dicomweb-cross-service-urls branch from e8dc14f to 37ef346 Compare May 9, 2026 16:22
Comment thread extensions/default/src/DicomWebDataSource/utils/applyServiceUrls.ts Outdated
…h coalescing

Use ?? instead of || for stowRoot fallback to respect explicit empty
strings. Wrap assignments in undefined checks so client URLs are not
overwritten when a root is not provided.

Signed-off-by: Agustin Bereciartua <bereciartua.agustin@gmail.com>
Comment thread extensions/default/src/DicomWebDataSource/utils/applyServiceUrls.ts Outdated
galenzo17 and others added 2 commits May 23, 2026 13:41
… avoid undefined stowURL

Move effectiveStowRoot computation inside each conditional block so it
cannot leak an undefined value when only one root is configured. In the
qidoRoot guard, chain the fallback as stowRoot ?? wadoRoot ?? qidoRoot
to handle the case where wadoRoot is undefined.

Add test covering the edge case of qidoRoot-only configuration.
Comment thread extensions/default/src/DicomWebDataSource/utils/applyServiceUrls.ts
…s unconditionally

When stowRoot and wadoRoot are set but qidoRoot is absent, the second
guard block does not run and wadoClient.stowURL stays at its constructor
default. Since storeInstances() uses wadoDicomWebClient, the explicit
stowRoot was silently ignored. Add an unconditional block that applies
stowRoot to both clients whenever it is defined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Incorrect URL Construction for DICOMweb QIDO/WADO Requests

1 participant