Skip to content

fix(DicomWebDataSource): apply bulkDataURI.transform to absolute BulkDataURIs - #6319

Open
pbaetz99 wants to merge 2 commits into
OHIF:masterfrom
pbaetz99:fix/bulkdatauri-transform-absolute
Open

pbaetz99 wants to merge 2 commits into
OHIF:masterfrom
pbaetz99:fix/bulkdatauri-transform-absolute

Conversation

@pbaetz99

@pbaetz99 pbaetz99 commented Sep 30, 2026 •

Copy link
Copy Markdown

Context

bulkDataURI.transform in the DICOMweb data source config has no effect when the server returns
an absolute BulkDataURI. A user reported this in
#4256 (comment) and patched the code locally.
This PR does not close #4256, whose original Orthanc problem was a different one.

It shows up when the DICOMweb server runs behind a TLS reverse proxy and returns BulkDataURIs as
http://..., while the viewer is served over https. This config should upgrade the URIs:

bulkDataURI: {
  enabled: true,
  transform: uri => uri.replace(/^http:/, 'https:'),
},

With this config, the request still goes to http://..., the browser blocks it as mixed content,
and dicomweb-client throws Error: request failed.

In extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts, transform writes into a
local BulkDataURI. The function copies that back to value.BulkDataURI only in the startsWith
branch and in the branches that resolve relative paths. An absolute http(s) URI reaches none of
them, and retrieveBulkData reads value.BulkDataURI, so it requests the untransformed URI. A
/path URI with a relative wadoRoot loses its transform the same way. The relative-path check
also reads value.BulkDataURI instead of the local, so when a transform turns an absolute or
relative URI into a /path, the result gets appended to the series URL. transform came in with
#4182 without a write-back for these cases.

Changes & Results

  • fixBulkDataURI writes the local URI back to value.BulkDataURI once, after transform and
    startsWith/prefixWith. The relative and /path branches overwrite it as before.
  • The relative-path check uses the local URI.
  • New fixBulkDataURI.test.ts next to the source. There was no unit test for this function.

BulkDataURI http://pacs.example.com/bulk/1, wadoRoot https://viewer.example.com/dicomweb:

transform before after
http: to https: http://pacs.example.com/bulk/1 https://pacs.example.com/bulk/1
host to /pacs https://viewer.example.com/dicomweb/studies/1.2.3/series/4.5.6//pacs/bulk/1 https://viewer.example.com/pacs/bulk/1

Without a transform, results do not change for any input: relative URIs, /path URIs,
startsWith/prefixWith and relativeResolution. The new test covers each of them.

Deployments that set transform and receive absolute or /path URIs will now see the transform
applied, where before it was ignored. dicom-web.md already describes transform without
limiting it to relative URIs, so I did not change the docs.

The microscopy viewport calls fixBulkDataURI a second time through cleanDenaturalizedDataset
with dataSource.getConfig(). For the DICOMweb data source that config is a JSON copy without
transform, so the second call gives the same result as before.

Testing

I ran everything below on Windows 11 with Node 24.21.0 and pnpm 11.5.2 (the packageManager
version, called as corepack pnpm), with dependencies installed from the repo lockfile.

The new test file, from the repo root:

pnpm exec jest --ci extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.test.ts
  • This branch: Tests: 14 passed, 14 total.

  • Same test file with fixBulkDataURI.ts restored from master 9ba15ec:
    Tests: 4 failed, 10 passed, 14 total. The 4 failures are the bugs this PR fixes:

    • applies transform to an absolute URI receives http://pacs.example.com/bulk/1.
    • resolves a transform result of /path against wadoRoot ..., with
      https://viewer.example.com/dicomweb and with /dicomweb, receives
      .../dicomweb/studies/1.2.3/series/4.5.6//pacs/bulk/1.
    • applies transform to a /path URI with a relative wadoRoot receives /bulk/1 instead of
      /pacs/bulk/1.

    The other 10 cases (no config, startsWith/prefixWith, /path, relative resolution) pass on
    master as well.

The extensions/default suite, the way CI runs it:

pnpm --filter @ohif/extension-default run test:unit:ci

This branch: Test Suites: 22 passed, 22 total, Tests: 164 passed, 164 total. Master 9ba15ec:
21 suites and 150 tests, all passed. The only difference is the new fixBulkDataURI.test.ts
(1 suite, 14 tests).

The other two steps of the CircleCI UNIT_TESTS job, pnpm run lint:compiler:ci and
pnpm run compiler:coverage:ci, exit 0 and print the same numbers as on master.
prettier --check passes on both changed files. eslint --config eslint.config.mjs reports
0 problems in fixBulkDataURI.ts and skips the test file, because the config ignores
**/*.test.*.

For a browser check with synthetic data I made two production builds with pnpm run build: one
from master 9ba15ec and one from master plus this commit. The second build also contained two other
local fixes of mine (overlay plane module, SR SOP class handler). They are not part of this PR and
do not touch fixBulkDataURI. Both builds used the same app-config.js, with a DICOMweb data
source pointed at a local mock server on 127.0.0.1. The mock serves one synthetic study with an
Encapsulated PDF. Its EncapsulatedDocument BulkDataURI is absolute and names a host that does
not resolve: http://internal-pacs.invalid:8080/dicomweb/studies/.../bulkdata/00420011. The
transform maps that host to the mock:

bulkDataURI: {
  enabled: true,
  relativeResolution: 'studies',
  transform: uri => uri.replace('http://internal-pacs.invalid:8080', 'http://127.0.0.1:18080'),
},

I opened the PDF series in headless Microsoft Edge 154.0.4258.37 and logged the network requests
over CDP:

  • master: GET http://internal-pacs.invalid:8080/dicomweb/studies/.../bulkdata/00420011 fails
    with net::ERR_NAME_NOT_RESOLVED. The console shows
    Failed to retrieve encapsulated document Error: request failed, and the viewport shows
    "Unable to retrieve this document".
  • this branch: GET http://127.0.0.1:18080/dicomweb/studies/.../bulkdata/00420011 returns 200
    and the PDF renders in the viewport. No request goes to internal-pacs.invalid.

I did not set up the https reverse proxy case from Context. The browser check runs through the same
code path, an absolute URI whose transform result was dropped, with a host rewrite instead of a
scheme rewrite. To try it against a real server, add a transform for its absolute BulkDataURIs,
open a study with an encapsulated PDF, and check the bulkdata request URL in the network tab.

Checklist

PR

  • My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

  • My code has been well-documented (function documentation, inline comments,
    etc.)

Public Documentation Updates

  • The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

  • OS: Windows 11
  • Node version: 24.21.0 (pnpm 11.5.2)
  • Browser: Microsoft Edge 154.0.4258.37 (headless, driven over CDP)

Summary by CodeRabbit

  • Bug Fixes
    • Bulk data links now consistently retain configured URI transformations and prefix adjustments, including absolute and server-relative links.
    • Relative links are resolved correctly with absolute or relative WADO roots and supported resolution settings.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@netlify

netlify Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for ohif-dev ready!

Name Link
🔨 Latest commit 0c0dd21
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/6abf87f9812e0b000880e53f
😎 Deploy Preview https://deploy-preview-6319--ohif-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 33ba94a4-9e1f-4105-ac86-cf23bef61eb0

📥 Commits

Reviewing files that changed from the base of the PR and between 8aad036 and 0c0dd21.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: e5204705-73b2-4c99-9fca-0adc0a6d8832

📥 Commits

Reviewing files that changed from the base of the PR and between 9ba15ec and 8aad036.

📒 Files selected for processing (2)
  • extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.test.ts
  • extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The change stores transformed and prefix-adjusted bulk data URIs before URI resolution. Tests cover absolute, server-relative, and relative URIs with different WADO roots and resolution settings.

Changes

Bulk data URI handling

Layer / File(s) Summary
Update and validate bulk data URIs
extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts, extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.test.ts
The function stores adjusted values in BulkDataURI before checking URI prefixes. Tests cover absolute URI passthrough and transformation, path resolution, prefix replacement, and relative URI resolution.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 8aad0

This change makes bulk data URI transforms apply to absolute and server-relative URIs, and behavior without a transform is unchanged. No actionable merge-blocking risk was identified.

🚥 Pre-merge checks | ✅ 3 | ❌ 1 | ❓ 1

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Issue #4256 requires PDFs to load in the reported Orthanc + OHIF v3 setup. The implementation now applies bulkDataURI.transform before absolute and server-relative URI handling. The added tests cove… Provide a reproducible check, or code-level evidence, for the Orthanc + OHIF v3 setup in #4256 that shows this URI change makes the PDF load. Confirm whether the reported No PDF viewer is installed symptom is caused by the transformed Bul…
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: applying bulkDataURI.transform to absolute BulkDataURIs. It uses the required semantic-release format and is concise.
Description check ✅ Passed The description is complete and relevant. It explains the issue, implementation, expected results, tests, browser validation, tested environment, and completed checklist items.
Out of Scope Changes check ✅ Passed The changed implementation and tests are limited to fixBulkDataURI behavior. They cover transforms, prefix replacement, absolute URIs, server-relative paths, and relative URI resolution. These chang…
Full details: Linked Issues check

Explanation

Issue #4256 requires PDFs to load in the reported Orthanc + OHIF v3 setup. The implementation now applies bulkDataURI.transform before absolute and server-relative URI handling. The added tests cover these URI paths. The reported browser check used synthetic data and did not test the Orthanc setup from #4256. The available evidence therefore does not establish that this PR resolves the linked issue.

Resolution

Provide a reproducible check, or code-level evidence, for the Orthanc + OHIF v3 setup in #4256 that shows this URI change makes the PDF load. Confirm whether the reported No PDF viewer is installed symptom is caused by the transformed BulkDataURI path.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…DataURIs

fixBulkDataURI runs bulkDataURI.transform on a local copy of the URI, but
writes the copy back to value.BulkDataURI only in the startsWith branch and
in the branches that resolve relative paths. An absolute http(s) URI reaches
none of them, so the transform result is dropped and retrieveBulkData
requests the original URI. A /path URI with a relative wadoRoot loses the
transform the same way. The relative-path check also read value.BulkDataURI
instead of the local copy, so a transform that returns a server-relative
/path was resolved against the series URL.

Write the local copy back once after transform and startsWith/prefixWith,
and use it in the relative-path check. The relative and /path branches
overwrite the value as before. Add fixBulkDataURI.test.ts.
@pbaetz99
pbaetz99 force-pushed the fix/bulkdatauri-transform-absolute branch from 1aedd33 to 8aad036 Compare September 30, 2026 14:22

This branch has not been deployed

No deployments
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.

PDF wont load orthanc with ohif setup

1 participant