fix: Use correct external URL for rendered responses with relative URI (#4236)

This commit is contained in:
Bill Wallace authored and GitHub committed 2024-06-17 22:36:03 -04:00
1 parent 6fc4390645
commit d8f6991dbe
9 files changed
+182 -24

No files matched your search

@@ -14,7 +14,7 @@ import getImageId from './utils/getImageId.js';
import dcmjs from 'dcmjs';
import { retrieveStudyMetadata, deleteStudyMetadataPromise } from './retrieveStudyMetadata.js';
import StaticWadoClient from './utils/StaticWadoClient';
import getDirectURL from '../utils/getDirectURL.js';
import getDirectURL from '../utils/getDirectURL';
import { fixBulkDataURI } from './utils/fixBulkDataURI';
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
@@ -393,10 +393,10 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
// The value.Value will be set with the bulkdata read value
// in which case it isn't necessary to re-read this.
if (value && value.BulkDataURI && !value.Value) {
// handle the scenarios where bulkDataURI is relative path
fixBulkDataURI(value, naturalized, dicomWebConfig);
// Provide a method to fetch bulkdata
value.retrieveBulkData = (options = {}) => {
// handle the scenarios where bulkDataURI is relative path
fixBulkDataURI(value, naturalized, dicomWebConfig);
const { mediaType } = options;
const useOptions = {
@@ -415,7 +415,6 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
: undefined,
...options,
};
// Todo: this needs to be from wado dicom web client
return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => {
// There are DICOM PDF cases where the first ArrayBuffer in the array is
// the bulk data and DICOM video cases where the second ArrayBuffer is
@@ -20,16 +20,23 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
// in case of the relative path, make it absolute. The current DICOM standard says
// the bulkdataURI is relative to the series. However, there are situations where
// it can be relative to the study too
if (!value.BulkDataURI.startsWith('http') && !value.BulkDataURI.startsWith('/')) {
if (dicomWebConfig.bulkDataURI?.relativeResolution === 'studies') {
value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/${value.BulkDataURI}`;
const { BulkDataURI } = value;
if (!BulkDataURI.startsWith('http') && !value.BulkDataURI.startsWith('/')) {
const { StudyInstanceUID, SeriesInstanceUID } = instance;
const isInstanceStart = BulkDataURI.startsWith('instances/') || BulkDataURI.startsWith('../');
if (
BulkDataURI.startsWith('series/') ||
BulkDataURI.startsWith('bulkdata/') ||
(dicomWebConfig.bulkDataURI?.relativeResolution === 'studies' && isInstanceStart)
) {
value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/${BulkDataURI}`;
} else if (
isInstanceStart ||
dicomWebConfig.bulkDataURI?.relativeResolution === 'series' ||
!dicomWebConfig.bulkDataURI?.relativeResolution
) {
value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/series/${instance.SeriesInstanceUID}/${value.BulkDataURI}`;
value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/${BulkDataURI}`;
}
return;
}
@@ -39,11 +46,11 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
// uri (e.g., bulkData: /bulk/1e, wado root: http://myserver.com/dicomweb, output: http://myserver.com/bulk/1e)
// and in case of relative wado root, we need to prepend the bulkdata uri to the wado root (e.g,. bulkData: /bulk/1e
// wado root: /dicomweb, output: /bulk/1e)
if (value.BulkDataURI[0] === '/') {
if (BulkDataURI[0] === '/') {
if (dicomWebConfig.wadoRoot.startsWith('http')) {
// Absolute wado root
const url = new URL(dicomWebConfig.wadoRoot);
value.BulkDataURI = `${url.origin}${value.BulkDataURI}`;
value.BulkDataURI = `${url.origin}${BulkDataURI}`;
} else {
// Relative wado root, we don't need to do anything, bulkdata uri is already correct
}
@@ -17,7 +17,12 @@ const createRenderedRetrieve = (config, params) => {
const { wadoRoot } = config;
const { instance, tag = 'PixelData' } = params;
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
const value = instance[tag];
if (value?.BulkDataURI?.indexOf('?') !== -1) {
// The value instance has parameters, so it should not revert to the rendered
return;
}
if (tag === 'PixelData' || tag === 'EncapsulatedDocument') {
return `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered`;
}
@@ -22,7 +22,7 @@ const getBulkdataValue = (config, params) => {
const value = instance[tag];
const { SeriesInstanceUID, SOPInstanceUID } = instance;
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
const BulkDataURI =
(value && value.BulkDataURI) ||
@@ -32,6 +32,11 @@ const getBulkdataValue = (config, params) => {
const acceptUri =
BulkDataURI + (hasAccept ? '' : (hasQuery ? '&' : '?') + `accept=${defaultType}`);
if (acceptUri.startsWith('series/')) {
const { wadoRoot } = config;
return `${wadoRoot}/studies/${StudyInstanceUID}/${acceptUri}`;
}
// The DICOMweb standard states that the default is multipart related, and then
// separately states that the accept parameter is the URL parameter equivalent of the accept header.
return acceptUri;
@@ -53,6 +53,12 @@ const _getDisplaySetsFromSeries = (instances, servicesManager, extensionManager)
const { Modality, SOPInstanceUID, SeriesDescription = 'VIDEO' } = instance;
const { SeriesNumber, SeriesDate, SeriesInstanceUID, StudyInstanceUID, NumberOfFrames, url } =
instance;
const videoUrl = dataSource.retrieve.directURL({
instance,
singlepart: 'video',
tag: 'PixelData',
url,
});
const displaySet = {
//plugin: id,
Modality,
@@ -66,12 +72,7 @@ const _getDisplaySetsFromSeries = (instances, servicesManager, extensionManager)
SOPClassHandlerId,
referencedImages: null,
measurements: null,
videoUrl: dataSource.retrieve.directURL({
instance,
singlepart: 'video',
tag: 'PixelData',
url,
}),
videoUrl,
instances: [instance],
thumbnailSrc: dataSource.retrieve.directURL({
instance,