From b1dc099c8336a1d5468b5d2d95b5b92a5674f5c2 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Wed, 6 Apr 2022 17:45:13 -0400 Subject: [PATCH 1/3] feat(dcmjs):Handle relative URI's --- src/api.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/api.js b/src/api.js index 8035b12..95e7815 100644 --- a/src/api.js +++ b/src/api.js @@ -1707,6 +1707,25 @@ class DICOMwebClient { ); } + /** + * Generate an absolute URI from a relative URI. + * If the URI contains : then it is already absolute, return it. + * If the URI starts with /, then just add it after the wadoURL + * Otherwise, assume the URL is relative to the wadoURL, and add studies/STUDYUID to it. + * @param {string} studyUid to use in the full URL + * @param {string} uri to convert to full URL + * @returns a URL to the requested resource. + */ + _handleRelativeURI(studyUid, uri) { + if (!uri || uri.indexOf(':') !== -1) { + return uri; + } + if (uri[0] === '/') { + return this.wadoURL + uri; + } + return `${this.wadoURL}/studies/${studyUid}/${uri}`; + } + /** * Retrieves and parses BulkData from a BulkDataURI location. * Decodes the multipart encoded data and returns the resulting data @@ -1715,15 +1734,17 @@ class DICOMwebClient { * See http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.5.5.html * * @param {Object} options - * @param {String} BulkDataURI - URI for retrieval of bulkdata + * @param {string} options.BulkDataURI to retrieve * @returns {Promise} Bulkdata parts */ retrieveBulkData(options) { if (!('BulkDataURI' in options)) { throw new Error('BulkDataURI is required.'); } + const { StudyInstanceUID, BulkDataURI } = options; - const url = options.BulkDataURI; + // Allow relative URI's, assume it is relative to the studyUID directory + const url = this._handleRelativeURI(StudyInstanceUID, BulkDataURI); const { mediaTypes, byteRange } = options; const { withCredentials = false } = options; const { progressCallback = false } = options; From 7d63979e9c77662a205fca0904dc8d6b3d79be67 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 21 Jun 2024 09:44:34 -0400 Subject: [PATCH 2/3] Fix lint issues --- .eslintrc.js | 2 +- .gitignore | 5 +++++ src/api.js | 28 ++++++++++++++-------------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 440ce67..12351c1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { root: true, extends: ['airbnb-base', 'prettier'], rules: { - 'import/extensions': "always", // Better for native ES Module usage + 'import/extensions': 0, 'no-console': 0, // We can remove this later 'no-underscore-dangle': 0, 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], diff --git a/.gitignore b/.gitignore index b1457a4..2e87056 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,11 @@ typings/ # Yarn lock file yarn.lock + +# Workspace files +*.code-workspace +.*.swp + # dotenv environment variables file .env diff --git a/src/api.js b/src/api.js index d21909b..be3dd43 100644 --- a/src/api.js +++ b/src/api.js @@ -246,7 +246,7 @@ class DICOMwebClient { } else if (request.responseType === 'arraybuffer') { resolve([request.response]); } else { - resolve(request.response); + resolve(request.response); } } else if (request.status === 202) { if (this.verbose) { @@ -284,7 +284,7 @@ class DICOMwebClient { } if (requestHooks && areValidRequestHooks(requestHooks)) { - const combinedHeaders = Object.assign({}, headers, this.headers); + const combinedHeaders = { ...headers, ...this.headers}; const metadata = { method, url, headers: combinedHeaders }; const pipeRequestHooks = functions => args => functions.reduce((props, fn) => fn(props, metadata), args); @@ -335,7 +335,7 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetApplicationJson(url, params = {}, progressCallback, withCredentials) { + _httpGetApplicationJson(url, params = {}, progressCallback=null, withCredentials=false) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -364,7 +364,7 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetApplicationPdf(url, params = {}, progressCallback, withCredentials) { + _httpGetApplicationPdf(url, params = {}, progressCallback = null, withCredentials = false) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -398,8 +398,8 @@ class DICOMwebClient { url, mediaTypes, params = {}, - progressCallback, - withCredentials, + progressCallback = null, + withCredentials = false, ) { let urlWithQueryParams = url; @@ -448,8 +448,8 @@ class DICOMwebClient { url, mediaTypes, params = {}, - progressCallback, - withCredentials, + progressCallback = null, + withCredentials = false, ) { let urlWithQueryParams = url; @@ -498,8 +498,8 @@ class DICOMwebClient { url, mediaTypes, params = {}, - progressCallback, - withCredentials, + progressCallback = null, + withCredentials = false, ) { let urlWithQueryParams = url; @@ -577,8 +577,8 @@ class DICOMwebClient { byteRange, params, rendered = false, - progressCallback, - withCredentials, + progressCallback = null, + withCredentials = false, ) { const headers = {}; let supportedMediaTypes; @@ -636,8 +636,8 @@ class DICOMwebClient { byteRange, params, rendered = false, - progressCallback, - withCredentials, + progressCallback = null, + withCredentials = false, ) { const headers = {}; let supportedMediaTypes; From 1e84801fe1dbf87eebc361af0ef2d6a147d1796b Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 21 Jun 2024 10:01:21 -0400 Subject: [PATCH 3/3] Make the relative URI standards compliant --- src/api.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/api.js b/src/api.js index be3dd43..2e670b3 100644 --- a/src/api.js +++ b/src/api.js @@ -1904,19 +1904,32 @@ class DICOMwebClient { * Generate an absolute URI from a relative URI. * If the URI contains : then it is already absolute, return it. * If the URI starts with /, then just add it after the wadoURL - * Otherwise, assume the URL is relative to the wadoURL, and add studies/STUDYUID to it. - * @param {string} studyUid to use in the full URL + * + * Otherwise, assume the URL is relative to the originally fetched URL - + * that needs to have been specified in the options as either: + * * `MetadataURI` + * * study UID for study relative path + * * series UID for series relative path + * * @param {string} uri to convert to full URL + * @param {object} options to get relative path from * @returns a URL to the requested resource. */ - _handleRelativeURI(studyUid, uri) { + _handleRelativeURI(uri, options = {}) { if (!uri || uri.indexOf(':') !== -1) { return uri; } if (uri[0] === '/') { return this.wadoURL + uri; } - return `${this.wadoURL}/studies/${studyUid}/${uri}`; + const { StudyInstanceUID: studyUid, SeriesInstanceUID: seriesUid, MetadataURI: metadataUri } = options; + if( metadataUri ) { + return metadataUri.indexOf(':')===-1 ? `${this.wadoURL}/${metadataUri}/${uri}` : `${metadataUri}/${uri}`; + } + // Not quite right, but this is a guess that the path is study relative if the URI starts with series, AND the seriesUID is available. + const isSeriesRelative = seriesUid && !uri.startsWith('series'); + + return isSeriesRelative ? `${this.wadoURL}/studies/${studyUid}/series/${seriesUid}/${uri}` : `${this.wadoURL}/studies/${studyUid}/${uri}`; } /** @@ -1936,10 +1949,10 @@ class DICOMwebClient { if (!('BulkDataURI' in options)) { throw new Error('BulkDataURI is required.'); } - const { StudyInstanceUID, BulkDataURI } = options; + const { BulkDataURI } = options; // Allow relative URI's, assume it is relative to the studyUID directory - const url = this._handleRelativeURI(StudyInstanceUID, BulkDataURI); + const url = this._handleRelativeURI(BulkDataURI, options); const { mediaTypes, byteRange } = options; const { withCredentials = false } = options; const { progressCallback = false } = options;