From dbbf4c83c2bf2404e24a1a53511c953fd85ec6e5 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 13 Jun 2025 15:16:47 -0400 Subject: [PATCH 1/5] fix: Missing variable name --- src/api.js | 300 +++++++++++++++++------------------------------------ 1 file changed, 96 insertions(+), 204 deletions(-) diff --git a/src/api.js b/src/api.js index e098fed..71b1320 100644 --- a/src/api.js +++ b/src/api.js @@ -1,7 +1,5 @@ import { multipartEncode, multipartDecode } from './message.js'; - - function isObject(obj) { return typeof obj === 'object' && obj !== null; } @@ -40,11 +38,11 @@ function areValidRequestHooks(requestHooks) { * @param {Request} request - Request options. */ const getRequestOptions = (request = {}) => ({ - instance: request.instance || new XMLHttpRequest(), - progressCallback: request.progressCallback || false, - withCredentials: request.withCredentials || false, - responseType: request.responseType -}) + instance: request.instance || new XMLHttpRequest(), + progressCallback: request.progressCallback || false, + withCredentials: request.withCredentials || false, + responseType: request.responseType, +}); const getFirstResult = result => result[0]; @@ -99,7 +97,9 @@ class DICOMwebClient { constructor(options) { this.baseURL = options.url; if (!this.baseURL) { - console.error('no DICOMweb base url provided - calls that require a URL will fail'); + console.error( + 'no DICOMweb base url provided - calls that require a URL will fail', + ); } if ('username' in options) { @@ -135,7 +135,10 @@ class DICOMwebClient { if (options.singlepart) { debugLog('use singlepart', options.singlepart); - this.singlepart = options.singlepart === true ? 'bulkdata,video,image' : options.singlepart; + this.singlepart = + options.singlepart === true + ? 'bulkdata,video,image' + : options.singlepart; } else { this.singlepart = ''; } @@ -154,16 +157,14 @@ class DICOMwebClient { this.verbose = options.verbose !== false; this.setDebug(options.debug); - - } /** - * Allows setting the debug log information. + * Allows setting the debug log information. * Note this is different from verbose in that verbose is whether to include warning/error information, defaulting to true - * - * @param {boolean} debugLevel - * @param {function} debugLogFunction to call with the debug output arguments. + * + * @param {boolean} debugLevel + * @param {function} debugLogFunction to call with the debug output arguments. */ setDebug(debugLevel = false, debugLogFunction = null) { this.debugLevel = !!debugLevel; @@ -172,13 +173,13 @@ class DICOMwebClient { /** * Gets debug flag - * + * * @returns true if debug logging is enabled */ getDebug() { return this.debugLevel; } - + /** * Sets verbose flag. * @@ -222,7 +223,9 @@ class DICOMwebClient { _httpRequest(url, method, headers = {}, request = {}) { const { errorInterceptor, requestHooks } = this; return new Promise((resolve, reject) => { - let requestInstance = request.instance ? request.instance : new XMLHttpRequest(); + let requestInstance = request.instance + ? request.instance + : new XMLHttpRequest(); requestInstance.open(method, url, true); if ('responseType' in request) { @@ -244,19 +247,21 @@ class DICOMwebClient { // Event triggered when upload starts requestInstance.onloadstart = function onloadstart() { - debugLog('upload started: ', url) + debugLog('upload started: ', url); }; // Event triggered when upload ends requestInstance.onloadend = function onloadend() { - debugLog('upload finished') + debugLog('upload finished'); }; // Handle response message requestInstance.onreadystatechange = () => { if (requestInstance.readyState === 4) { if (requestInstance.status === 200) { - const contentType = requestInstance.getResponseHeader('Content-Type'); + const contentType = requestInstance.getResponseHeader( + 'Content-Type', + ); // Automatically distinguishes between multipart and singlepart in an array buffer, and // converts them into a consistent type. if (contentType && contentType.indexOf('multipart') !== -1) { @@ -360,11 +365,7 @@ class DICOMwebClient { request.responseType = 'json'; - return this._httpGet( - urlWithQueryParams, - headers, - request - ); + return this._httpGet(urlWithQueryParams, headers, request); } /** @@ -387,13 +388,9 @@ class DICOMwebClient { } const headers = { Accept: MEDIATYPES.PDF }; - request.responseType = 'json' + request.responseType = 'json'; - return this._httpGet( - urlWithQueryParams, - headers, - request, - ); + return this._httpGet(urlWithQueryParams, headers, request); } /** @@ -407,12 +404,7 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetImage( - url, - mediaTypes, - params = {}, - request = {} - ) { + _httpGetImage(url, mediaTypes, params = {}, request = {}) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -435,13 +427,9 @@ class DICOMwebClient { supportedMediaTypes, ); const headers = { Accept: acceptHeaderFieldValue }; - request.responseType = 'arraybuffer' + request.responseType = 'arraybuffer'; - return this._httpGet( - urlWithQueryParams, - headers, - request, - ); + return this._httpGet(urlWithQueryParams, headers, request); } /** @@ -455,12 +443,7 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetText( - url, - mediaTypes, - params = {}, - request = {} - ) { + _httpGetText(url, mediaTypes, params = {}, request = {}) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -485,11 +468,7 @@ class DICOMwebClient { const headers = { Accept: acceptHeaderFieldValue }; request.responseType = 'arraybuffer'; - return this._httpGet( - urlWithQueryParams, - headers, - request, - ); + return this._httpGet(urlWithQueryParams, headers, request); } /** @@ -503,12 +482,7 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetVideo( - url, - mediaTypes, - params = {}, - request = {} - ) { + _httpGetVideo(url, mediaTypes, params = {}, request = {}) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -532,11 +506,7 @@ class DICOMwebClient { const headers = { Accept: acceptHeaderFieldValue }; request.responseType = 'arraybuffer'; - return this._httpGet( - urlWithQueryParams, - headers, - request, - ); + return this._httpGet(urlWithQueryParams, headers, request); } /** @@ -584,7 +554,7 @@ class DICOMwebClient { byteRange, params, rendered = false, - request = {} + request = {}, ) { const headers = {}; let supportedMediaTypes; @@ -644,7 +614,7 @@ class DICOMwebClient { byteRange, params, rendered = false, - request = {} + request = {}, ) { const headers = {}; let supportedMediaTypes; @@ -694,12 +664,7 @@ class DICOMwebClient { * @private * @returns {Promise} Content of HTTP message body parts */ - _httpGetMultipartApplicationDicom( - url, - mediaTypes, - params, - request = {} - ) { + _httpGetMultipartApplicationDicom(url, mediaTypes, params, request = {}) { const headers = {}; const defaultMediaType = 'application/dicom'; const supportedMediaTypes = { @@ -758,7 +723,7 @@ class DICOMwebClient { mediaTypes, byteRange, params, - request = {} + request = {}, ) { const headers = {}; const defaultMediaType = 'application/octet-stream'; @@ -780,7 +745,7 @@ class DICOMwebClient { supportedMediaTypes, ); - request.responseType = 'arraybuffer' + request.responseType = 'arraybuffer'; return this._httpGet(url, headers, request); } @@ -797,7 +762,8 @@ class DICOMwebClient { */ _httpPost(url, headers, data, request) { return this._httpRequest(url, 'post', headers, { - ...request, data + ...request, + data, }); } @@ -813,12 +779,7 @@ class DICOMwebClient { */ _httpPostApplicationJson(url, data, request) { const headers = { 'Content-Type': MEDIATYPES.DICOM_JSON }; - return this._httpPost( - url, - headers, - data, - request, - ); + return this._httpPost(url, headers, data, request); } /** @@ -949,7 +910,7 @@ class DICOMwebClient { Array.isArray(supportedMediaTypes) && !supportedMediaTypes.includes(mediaType) ) { - if( this.verbose ) { + if (this.verbose) { console.warn( `Media type ${mediaType} is not supported for requested resource`, ); @@ -960,8 +921,10 @@ class DICOMwebClient { fieldValueParts.push(fieldValue); }); - if( !fieldValueParts.length ) { - throw new Error(`No acceptable media types found among ${JSON.stringify(mediaTypes)}`); + if (!fieldValueParts.length) { + throw new Error( + `No acceptable media types found among ${JSON.stringify(mediaTypes)}`, + ); } return fieldValueParts.join(', '); @@ -1049,7 +1012,7 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1070,7 +1033,7 @@ class DICOMwebClient { } debugLog(`retrieve metadata of study ${options.studyInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/metadata`; - const request =getRequestOptions(options.request) + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1093,8 +1056,8 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - - const request = getRequestOptions(options.request) + + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1123,9 +1086,9 @@ class DICOMwebClient { debugLog(`retrieve metadata of series ${options.seriesInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}/metadata`; - - const request = getRequestOptions(options.request) - return this._httpGetApplicationJson(url, {}, false, withCredentials); + + const request = getRequestOptions(options.request); + return this._httpGetApplicationJson(url, {}, request); } /** @@ -1144,14 +1107,10 @@ class DICOMwebClient { if ('studyInstanceUID' in options) { url += `/studies/${options.studyInstanceUID}`; if ('seriesInstanceUID' in options) { - debugLog( - `search for instances of series ${options.seriesInstanceUID}`, - ); + debugLog(`search for instances of series ${options.seriesInstanceUID}`); url += `/series/${options.seriesInstanceUID}`; } else { - debugLog( - `search for instances of study ${options.studyInstanceUID}`, - ); + debugLog(`search for instances of study ${options.studyInstanceUID}`); } } else { debugLog('search for instances'); @@ -1160,7 +1119,7 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1227,8 +1186,8 @@ class DICOMwebClient { } debugLog(`retrieve metadata of instance ${options.sopInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}/instances/${options.sopInstanceUID}/metadata`; - - const request = getRequestOptions(options.request) + + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1275,8 +1234,8 @@ class DICOMwebClient { }/frames/${options.frameNumbers.toString()}`; const { mediaTypes } = options; - - const request = getRequestOptions(options.request) + + const request = getRequestOptions(options.request); if (!mediaTypes) { return this._httpGetMultipartApplicationOctetStream( @@ -1359,11 +1318,11 @@ class DICOMwebClient { ); } - /** - * Element in mediaTypes parameter - * @typedef {Object} MediaType - * @param {String} [MediaType.mediaType] - ie 'image/jpeg', 'image/png'... - */ + /** + * Element in mediaTypes parameter + * @typedef {Object} MediaType + * @param {String} [MediaType.mediaType] - ie 'image/jpeg', 'image/png'... + */ /** * Retrieves an individual, server-side rendered DICOM Instance. @@ -1398,51 +1357,28 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); if (!mediaTypes) { request.responseType = 'arraybuffer'; if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet( - url, - headers, - request, - ); + return this._httpGet(url, headers, request); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage( - url, - mediaTypes, - queryParams, - request, - ); + return this._httpGetImage(url, mediaTypes, queryParams, request); } if (commonMediaType.startsWith('video')) { - return this._httpGetVideo( - url, - mediaTypes, - queryParams, - request - ); + return this._httpGetVideo(url, mediaTypes, queryParams, request); } if (commonMediaType.startsWith('text')) { - return this._httpGetText( - url, - mediaTypes, - queryParams, - request, - ); + return this._httpGetText(url, mediaTypes, queryParams, request); } if (commonMediaType === MEDIATYPES.PDF) { - return this._httpGetApplicationPdf( - url, - queryParams, - request, - ); + return this._httpGetApplicationPdf(url, queryParams, request); } throw new Error( @@ -1484,29 +1420,20 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - - const request = getRequestOptions(options.request) + + const request = getRequestOptions(options.request); if (!mediaTypes) { request.responseType = 'arraybuffer'; if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet( - url, - headers, - request - ); + return this._httpGet(url, headers, request); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage( - url, - mediaTypes, - queryParams, - request - ); + return this._httpGetImage(url, mediaTypes, queryParams, request); } throw new Error( @@ -1563,7 +1490,7 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); if (!mediaTypes) { if (queryParams) { @@ -1575,20 +1502,10 @@ class DICOMwebClient { const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage( - url, - mediaTypes, - queryParams, - request - ); + return this._httpGetImage(url, mediaTypes, queryParams, request); } if (commonMediaType.startsWith('video')) { - return this._httpGetVideo( - url, - mediaTypes, - queryParams, - request - ); + return this._httpGetVideo(url, mediaTypes, queryParams, request); } throw new Error( @@ -1651,21 +1568,12 @@ class DICOMwebClient { if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet( - url, - headers, - request - ); + return this._httpGet(url, headers, request); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage( - url, - mediaTypes, - queryParams, - request - ); + return this._httpGetImage(url, mediaTypes, queryParams, request); } throw new Error( @@ -1699,14 +1607,14 @@ class DICOMwebClient { const { mediaTypes } = options; - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); if (!mediaTypes) { return this._httpGetMultipartApplicationDicom( url, false, false, - request + request, ).then(getFirstResult); } @@ -1716,7 +1624,7 @@ class DICOMwebClient { url, mediaTypes, false, - request + request, ).then(getFirstResult); } @@ -1745,15 +1653,10 @@ class DICOMwebClient { const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}`; const { mediaTypes } = options; - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); if (!mediaTypes) { - return this._httpGetMultipartApplicationDicom( - url, - false, - false, - request - ); + return this._httpGetMultipartApplicationDicom(url, false, false, request); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); @@ -1762,7 +1665,7 @@ class DICOMwebClient { url, mediaTypes, false, - request + request, ); } @@ -1790,12 +1693,7 @@ class DICOMwebClient { const request = getRequestOptions(options.request); if (!mediaTypes) { - return this._httpGetMultipartApplicationDicom( - url, - false, - false, - request - ); + return this._httpGetMultipartApplicationDicom(url, false, false, request); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); @@ -1804,7 +1702,7 @@ class DICOMwebClient { url, mediaTypes, false, - request + request, ); } @@ -1845,7 +1743,7 @@ class DICOMwebClient { try { const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); - if (commonMediaType==='image/') { + if (commonMediaType === 'image/') { return this._httpGetMultipartImage( url, mediaTypes, @@ -1856,7 +1754,7 @@ class DICOMwebClient { withCredentials, ); } - } catch(e) { + } catch (e) { // No-op - this happens sometimes if trying to fetch the specific desired type but want to fallback to octet-stream } } @@ -1867,7 +1765,7 @@ class DICOMwebClient { mediaTypes, byteRange, false, - request + request, ); } @@ -1893,18 +1791,12 @@ class DICOMwebClient { const { data, boundary } = multipartEncode(options.datasets); const headers = { 'Content-Type': `multipart/related; type="application/dicom"; boundary="${boundary}"`, - }; + }; const request = getRequestOptions(options.request); - return this._httpPost( - url, - headers, - data, - request - ); + return this._httpPost(url, headers, data, request); } } - export { DICOMwebClient }; export default DICOMwebClient; From fcd997dfbbd439d8dc588055fbc04fb02687e369 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 13 Jun 2025 15:22:25 -0400 Subject: [PATCH 2/5] fix: linting issues --- .eslintrc.js | 2 +- src/api.js | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 440ce67..ae46fc1 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': 2, // Better for native ES Module usage 'no-console': 0, // We can remove this later 'no-underscore-dangle': 0, 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], diff --git a/src/api.js b/src/api.js index 71b1320..44e6f9e 100644 --- a/src/api.js +++ b/src/api.js @@ -1,4 +1,4 @@ -import { multipartEncode, multipartDecode } from './message.js'; +import { multipartEncode, multipartDecode } from './message'; function isObject(obj) { return typeof obj === 'object' && obj !== null; @@ -307,7 +307,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); @@ -1103,7 +1103,6 @@ class DICOMwebClient { */ searchForInstances(options = {}) { let url = this.qidoURL; - let withCredentials = false; if ('studyInstanceUID' in options) { url += `/studies/${options.studyInstanceUID}`; if ('seriesInstanceUID' in options) { @@ -1750,8 +1749,6 @@ class DICOMwebClient { byteRange, false, false, - progressCallback, - withCredentials, ); } } catch (e) { From 2efe1aefb14eef7105ed5d2d211a19b3951842e4 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 13 Jun 2025 15:46:47 -0400 Subject: [PATCH 3/5] fix: Undo format changes --- src/api.js | 304 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 207 insertions(+), 97 deletions(-) diff --git a/src/api.js b/src/api.js index 44e6f9e..adbcfba 100644 --- a/src/api.js +++ b/src/api.js @@ -1,4 +1,6 @@ -import { multipartEncode, multipartDecode } from './message'; +import { multipartEncode, multipartDecode } from './message.js'; + + function isObject(obj) { return typeof obj === 'object' && obj !== null; @@ -38,11 +40,11 @@ function areValidRequestHooks(requestHooks) { * @param {Request} request - Request options. */ const getRequestOptions = (request = {}) => ({ - instance: request.instance || new XMLHttpRequest(), - progressCallback: request.progressCallback || false, - withCredentials: request.withCredentials || false, - responseType: request.responseType, -}); + instance: request.instance || new XMLHttpRequest(), + progressCallback: request.progressCallback || false, + withCredentials: request.withCredentials || false, + responseType: request.responseType +}) const getFirstResult = result => result[0]; @@ -97,9 +99,7 @@ class DICOMwebClient { constructor(options) { this.baseURL = options.url; if (!this.baseURL) { - console.error( - 'no DICOMweb base url provided - calls that require a URL will fail', - ); + console.error('no DICOMweb base url provided - calls that require a URL will fail'); } if ('username' in options) { @@ -135,10 +135,7 @@ class DICOMwebClient { if (options.singlepart) { debugLog('use singlepart', options.singlepart); - this.singlepart = - options.singlepart === true - ? 'bulkdata,video,image' - : options.singlepart; + this.singlepart = options.singlepart === true ? 'bulkdata,video,image' : options.singlepart; } else { this.singlepart = ''; } @@ -157,14 +154,16 @@ class DICOMwebClient { this.verbose = options.verbose !== false; this.setDebug(options.debug); + + } /** - * Allows setting the debug log information. + * Allows setting the debug log information. * Note this is different from verbose in that verbose is whether to include warning/error information, defaulting to true - * - * @param {boolean} debugLevel - * @param {function} debugLogFunction to call with the debug output arguments. + * + * @param {boolean} debugLevel + * @param {function} debugLogFunction to call with the debug output arguments. */ setDebug(debugLevel = false, debugLogFunction = null) { this.debugLevel = !!debugLevel; @@ -173,13 +172,13 @@ class DICOMwebClient { /** * Gets debug flag - * + * * @returns true if debug logging is enabled */ getDebug() { return this.debugLevel; } - + /** * Sets verbose flag. * @@ -223,9 +222,7 @@ class DICOMwebClient { _httpRequest(url, method, headers = {}, request = {}) { const { errorInterceptor, requestHooks } = this; return new Promise((resolve, reject) => { - let requestInstance = request.instance - ? request.instance - : new XMLHttpRequest(); + let requestInstance = request.instance ? request.instance : new XMLHttpRequest(); requestInstance.open(method, url, true); if ('responseType' in request) { @@ -247,21 +244,19 @@ class DICOMwebClient { // Event triggered when upload starts requestInstance.onloadstart = function onloadstart() { - debugLog('upload started: ', url); + debugLog('upload started: ', url) }; // Event triggered when upload ends requestInstance.onloadend = function onloadend() { - debugLog('upload finished'); + debugLog('upload finished') }; // Handle response message requestInstance.onreadystatechange = () => { if (requestInstance.readyState === 4) { if (requestInstance.status === 200) { - const contentType = requestInstance.getResponseHeader( - 'Content-Type', - ); + const contentType = requestInstance.getResponseHeader('Content-Type'); // Automatically distinguishes between multipart and singlepart in an array buffer, and // converts them into a consistent type. if (contentType && contentType.indexOf('multipart') !== -1) { @@ -307,7 +302,7 @@ class DICOMwebClient { } if (requestHooks && areValidRequestHooks(requestHooks)) { - const combinedHeaders = { ...headers, ...this.headers }; + const combinedHeaders = Object.assign({}, headers, this.headers); const metadata = { method, url, headers: combinedHeaders }; const pipeRequestHooks = functions => args => functions.reduce((props, fn) => fn(props, metadata), args); @@ -365,7 +360,11 @@ class DICOMwebClient { request.responseType = 'json'; - return this._httpGet(urlWithQueryParams, headers, request); + return this._httpGet( + urlWithQueryParams, + headers, + request + ); } /** @@ -388,9 +387,13 @@ class DICOMwebClient { } const headers = { Accept: MEDIATYPES.PDF }; - request.responseType = 'json'; + request.responseType = 'json' - return this._httpGet(urlWithQueryParams, headers, request); + return this._httpGet( + urlWithQueryParams, + headers, + request, + ); } /** @@ -404,7 +407,12 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetImage(url, mediaTypes, params = {}, request = {}) { + _httpGetImage( + url, + mediaTypes, + params = {}, + request = {} + ) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -427,9 +435,13 @@ class DICOMwebClient { supportedMediaTypes, ); const headers = { Accept: acceptHeaderFieldValue }; - request.responseType = 'arraybuffer'; + request.responseType = 'arraybuffer' - return this._httpGet(urlWithQueryParams, headers, request); + return this._httpGet( + urlWithQueryParams, + headers, + request, + ); } /** @@ -443,7 +455,12 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetText(url, mediaTypes, params = {}, request = {}) { + _httpGetText( + url, + mediaTypes, + params = {}, + request = {} + ) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -468,7 +485,11 @@ class DICOMwebClient { const headers = { Accept: acceptHeaderFieldValue }; request.responseType = 'arraybuffer'; - return this._httpGet(urlWithQueryParams, headers, request); + return this._httpGet( + urlWithQueryParams, + headers, + request, + ); } /** @@ -482,7 +503,12 @@ class DICOMwebClient { * @return {*} * @private */ - _httpGetVideo(url, mediaTypes, params = {}, request = {}) { + _httpGetVideo( + url, + mediaTypes, + params = {}, + request = {} + ) { let urlWithQueryParams = url; if (typeof params === 'object') { @@ -506,7 +532,11 @@ class DICOMwebClient { const headers = { Accept: acceptHeaderFieldValue }; request.responseType = 'arraybuffer'; - return this._httpGet(urlWithQueryParams, headers, request); + return this._httpGet( + urlWithQueryParams, + headers, + request, + ); } /** @@ -554,7 +584,7 @@ class DICOMwebClient { byteRange, params, rendered = false, - request = {}, + request = {} ) { const headers = {}; let supportedMediaTypes; @@ -614,7 +644,7 @@ class DICOMwebClient { byteRange, params, rendered = false, - request = {}, + request = {} ) { const headers = {}; let supportedMediaTypes; @@ -664,7 +694,12 @@ class DICOMwebClient { * @private * @returns {Promise} Content of HTTP message body parts */ - _httpGetMultipartApplicationDicom(url, mediaTypes, params, request = {}) { + _httpGetMultipartApplicationDicom( + url, + mediaTypes, + params, + request = {} + ) { const headers = {}; const defaultMediaType = 'application/dicom'; const supportedMediaTypes = { @@ -723,7 +758,7 @@ class DICOMwebClient { mediaTypes, byteRange, params, - request = {}, + request = {} ) { const headers = {}; const defaultMediaType = 'application/octet-stream'; @@ -745,7 +780,7 @@ class DICOMwebClient { supportedMediaTypes, ); - request.responseType = 'arraybuffer'; + request.responseType = 'arraybuffer' return this._httpGet(url, headers, request); } @@ -762,8 +797,7 @@ class DICOMwebClient { */ _httpPost(url, headers, data, request) { return this._httpRequest(url, 'post', headers, { - ...request, - data, + ...request, data }); } @@ -779,7 +813,12 @@ class DICOMwebClient { */ _httpPostApplicationJson(url, data, request) { const headers = { 'Content-Type': MEDIATYPES.DICOM_JSON }; - return this._httpPost(url, headers, data, request); + return this._httpPost( + url, + headers, + data, + request, + ); } /** @@ -910,7 +949,7 @@ class DICOMwebClient { Array.isArray(supportedMediaTypes) && !supportedMediaTypes.includes(mediaType) ) { - if (this.verbose) { + if( this.verbose ) { console.warn( `Media type ${mediaType} is not supported for requested resource`, ); @@ -921,10 +960,8 @@ class DICOMwebClient { fieldValueParts.push(fieldValue); }); - if (!fieldValueParts.length) { - throw new Error( - `No acceptable media types found among ${JSON.stringify(mediaTypes)}`, - ); + if( !fieldValueParts.length ) { + throw new Error(`No acceptable media types found among ${JSON.stringify(mediaTypes)}`); } return fieldValueParts.join(', '); @@ -1012,7 +1049,7 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1033,7 +1070,7 @@ class DICOMwebClient { } debugLog(`retrieve metadata of study ${options.studyInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/metadata`; - const request = getRequestOptions(options.request); + const request =getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1056,8 +1093,8 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - - const request = getRequestOptions(options.request); + + const request = getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1086,8 +1123,8 @@ class DICOMwebClient { debugLog(`retrieve metadata of series ${options.seriesInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}/metadata`; - - const request = getRequestOptions(options.request); + + const request = getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1106,10 +1143,14 @@ class DICOMwebClient { if ('studyInstanceUID' in options) { url += `/studies/${options.studyInstanceUID}`; if ('seriesInstanceUID' in options) { - debugLog(`search for instances of series ${options.seriesInstanceUID}`); + debugLog( + `search for instances of series ${options.seriesInstanceUID}`, + ); url += `/series/${options.seriesInstanceUID}`; } else { - debugLog(`search for instances of study ${options.studyInstanceUID}`); + debugLog( + `search for instances of study ${options.studyInstanceUID}`, + ); } } else { debugLog('search for instances'); @@ -1118,7 +1159,7 @@ class DICOMwebClient { if ('queryParams' in options) { url += DICOMwebClient._parseQueryParameters(options.queryParams); } - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1185,8 +1226,8 @@ class DICOMwebClient { } debugLog(`retrieve metadata of instance ${options.sopInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}/instances/${options.sopInstanceUID}/metadata`; - - const request = getRequestOptions(options.request); + + const request = getRequestOptions(options.request) return this._httpGetApplicationJson(url, {}, request); } @@ -1233,8 +1274,8 @@ class DICOMwebClient { }/frames/${options.frameNumbers.toString()}`; const { mediaTypes } = options; - - const request = getRequestOptions(options.request); + + const request = getRequestOptions(options.request) if (!mediaTypes) { return this._httpGetMultipartApplicationOctetStream( @@ -1317,11 +1358,11 @@ class DICOMwebClient { ); } - /** - * Element in mediaTypes parameter - * @typedef {Object} MediaType - * @param {String} [MediaType.mediaType] - ie 'image/jpeg', 'image/png'... - */ + /** + * Element in mediaTypes parameter + * @typedef {Object} MediaType + * @param {String} [MediaType.mediaType] - ie 'image/jpeg', 'image/png'... + */ /** * Retrieves an individual, server-side rendered DICOM Instance. @@ -1356,28 +1397,51 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) if (!mediaTypes) { request.responseType = 'arraybuffer'; if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet(url, headers, request); + return this._httpGet( + url, + headers, + request, + ); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage(url, mediaTypes, queryParams, request); + return this._httpGetImage( + url, + mediaTypes, + queryParams, + request, + ); } if (commonMediaType.startsWith('video')) { - return this._httpGetVideo(url, mediaTypes, queryParams, request); + return this._httpGetVideo( + url, + mediaTypes, + queryParams, + request + ); } if (commonMediaType.startsWith('text')) { - return this._httpGetText(url, mediaTypes, queryParams, request); + return this._httpGetText( + url, + mediaTypes, + queryParams, + request, + ); } if (commonMediaType === MEDIATYPES.PDF) { - return this._httpGetApplicationPdf(url, queryParams, request); + return this._httpGetApplicationPdf( + url, + queryParams, + request, + ); } throw new Error( @@ -1419,20 +1483,29 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - - const request = getRequestOptions(options.request); + + const request = getRequestOptions(options.request) if (!mediaTypes) { request.responseType = 'arraybuffer'; if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet(url, headers, request); + return this._httpGet( + url, + headers, + request + ); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage(url, mediaTypes, queryParams, request); + return this._httpGetImage( + url, + mediaTypes, + queryParams, + request + ); } throw new Error( @@ -1489,7 +1562,7 @@ class DICOMwebClient { const { mediaTypes, queryParams } = options; const headers = {}; - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) if (!mediaTypes) { if (queryParams) { @@ -1501,10 +1574,20 @@ class DICOMwebClient { const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage(url, mediaTypes, queryParams, request); + return this._httpGetImage( + url, + mediaTypes, + queryParams, + request + ); } if (commonMediaType.startsWith('video')) { - return this._httpGetVideo(url, mediaTypes, queryParams, request); + return this._httpGetVideo( + url, + mediaTypes, + queryParams, + request + ); } throw new Error( @@ -1567,12 +1650,21 @@ class DICOMwebClient { if (queryParams) { url += DICOMwebClient._parseQueryParameters(queryParams); } - return this._httpGet(url, headers, request); + return this._httpGet( + url, + headers, + request + ); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); if (commonMediaType.startsWith('image')) { - return this._httpGetImage(url, mediaTypes, queryParams, request); + return this._httpGetImage( + url, + mediaTypes, + queryParams, + request + ); } throw new Error( @@ -1606,14 +1698,14 @@ class DICOMwebClient { const { mediaTypes } = options; - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) if (!mediaTypes) { return this._httpGetMultipartApplicationDicom( url, false, false, - request, + request ).then(getFirstResult); } @@ -1623,7 +1715,7 @@ class DICOMwebClient { url, mediaTypes, false, - request, + request ).then(getFirstResult); } @@ -1652,10 +1744,15 @@ class DICOMwebClient { const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}`; const { mediaTypes } = options; - const request = getRequestOptions(options.request); + const request = getRequestOptions(options.request) if (!mediaTypes) { - return this._httpGetMultipartApplicationDicom(url, false, false, request); + return this._httpGetMultipartApplicationDicom( + url, + false, + false, + request + ); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); @@ -1664,7 +1761,7 @@ class DICOMwebClient { url, mediaTypes, false, - request, + request ); } @@ -1692,7 +1789,12 @@ class DICOMwebClient { const request = getRequestOptions(options.request); if (!mediaTypes) { - return this._httpGetMultipartApplicationDicom(url, false, false, request); + return this._httpGetMultipartApplicationDicom( + url, + false, + false, + request + ); } const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); @@ -1701,7 +1803,7 @@ class DICOMwebClient { url, mediaTypes, false, - request, + request ); } @@ -1742,16 +1844,18 @@ class DICOMwebClient { try { const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes); - if (commonMediaType === 'image/') { + if (commonMediaType==='image/') { return this._httpGetMultipartImage( url, mediaTypes, byteRange, false, false, + progressCallback, + withCredentials, ); } - } catch (e) { + } catch(e) { // No-op - this happens sometimes if trying to fetch the specific desired type but want to fallback to octet-stream } } @@ -1762,7 +1866,7 @@ class DICOMwebClient { mediaTypes, byteRange, false, - request, + request ); } @@ -1788,12 +1892,18 @@ class DICOMwebClient { const { data, boundary } = multipartEncode(options.datasets); const headers = { 'Content-Type': `multipart/related; type="application/dicom"; boundary="${boundary}"`, - }; + }; const request = getRequestOptions(options.request); - return this._httpPost(url, headers, data, request); + return this._httpPost( + url, + headers, + data, + request + ); } } + export { DICOMwebClient }; export default DICOMwebClient; From 66c1aee4f99ef763f17cbe4d0d15d3d4b48759d6 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Mon, 16 Jun 2025 17:45:23 -0400 Subject: [PATCH 4/5] fix: Instance TSUID is needed to decode images --- .github/workflows/publish-package.yml | 2 +- .github/workflows/tests.yml | 2 +- src/api.js | 10 ++-- src/message.js | 69 +++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index c689570..4884a99 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -7,7 +7,7 @@ on: jobs: publish-package: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest environment: publish steps: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9ce8b96..82ba4ad 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,7 +6,7 @@ on: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/src/api.js b/src/api.js index adbcfba..40698ed 100644 --- a/src/api.js +++ b/src/api.js @@ -1,6 +1,4 @@ -import { multipartEncode, multipartDecode } from './message.js'; - - +import { multipartEncode, multipartDecode, addHeaders } from './message.js'; function isObject(obj) { return typeof obj === 'object' && obj !== null; @@ -256,12 +254,16 @@ class DICOMwebClient { requestInstance.onreadystatechange = () => { if (requestInstance.readyState === 4) { if (requestInstance.status === 200) { - const contentType = requestInstance.getResponseHeader('Content-Type'); + const contentType = requestInstance.getResponseHeader( + 'Content-Type', + ); + const headers = requestInstance.getAllResponseHeaders(); // Automatically distinguishes between multipart and singlepart in an array buffer, and // converts them into a consistent type. if (contentType && contentType.indexOf('multipart') !== -1) { resolve(multipartDecode(requestInstance.response)); } else if (requestInstance.responseType === 'arraybuffer') { + addHeaders(requestInstance.response, headers); resolve([requestInstance.response]); } else { resolve(requestInstance.response); diff --git a/src/message.js b/src/message.js index ab3e9cc..ccb7224 100644 --- a/src/message.js +++ b/src/message.js @@ -38,7 +38,7 @@ function identifyBoundary(header) { const parts = header.split('\r\n'); for (let i = 0; i < parts.length; i++) { - if (parts[i].substr(0, 2) === '--') { + if (parts[i].substring(0, 2) === '--') { return parts[i]; } } @@ -179,16 +179,72 @@ function multipartEncode( }; } +/** + * Splits the header string into parts and extracts the simple contentType + * and transferSyntaxUID, assigning them, plus the headers map into the destination object. + * + * @param {*} destination + * @param {string} headerString + */ +function addHeaders(destination, headerString) { + if (!headerString) { + return; + } + const headerLines = headerString.split('\r\n').filter(Boolean); + const headers = new Map(); + let transferSyntaxUID = null, + contentType = null; + + for (const line of headerLines) { + const colon = line.indexOf(':'); + if (colon === -1) { + continue; + } + const name = line.substring(0, colon).toLowerCase(); + const value = line.substring(colon + 1).trim(); + if (headers.has(name)) { + headers.get(name).push(value); + } else { + headers.set(name, [value]); + } + if (name === 'content-type') { + const endSimpleType = value.indexOf(';'); + contentType ||= value.substring( + 0, + endSimpleType === -1 ? value.length : endSimpleType, + ); + const transferSyntaxStart = value.indexOf('transfer-syntax='); + if (transferSyntaxStart !== -1) { + const endTsuid = value.indexOf(';', transferSyntaxStart); + transferSyntaxUID = value.substring( + transferSyntaxStart + 16, + endTsuid === -1 ? value.length : endTsuid, + ); + } + } + } + + Object.defineProperty(destination, 'headers', { value: headers }); + Object.defineProperty(destination, 'contentType', { value: contentType }); + Object.defineProperty(destination, 'transferSyntaxUID', { + value: transferSyntaxUID, + }); +} + /** * Decode a Multipart encoded ArrayBuffer and return the components as an Array. * * @param {ArrayBuffer} response Data encoded as a 'multipart/related' message - * @returns {Array} The content + * @returns {Uint8Array[]} The content as an array of Uint8Array + * Each item shall have a contentType value, and a transferSyntaxUID if available, + * as well as the headers Map. See parseHeaders for output. + * */ function multipartDecode(response) { // Use the raw data if it is provided in an appropriate format - const message = ArrayBuffer.isView(response) ? response : new Uint8Array(response); - + const message = ArrayBuffer.isView(response) + ? response + : new Uint8Array(response); /* Set a maximum length to search for the header boundaries, otherwise findToken can run for a long time */ @@ -211,6 +267,8 @@ function multipartDecode(response) { const boundaryLength = boundary.length; const components = []; + const headers = header.substring(boundary.length + 2); + let offset = boundaryLength; // Loop until we cannot find any more boundaries @@ -240,6 +298,8 @@ function multipartDecode(response) { // Extract data from response message, excluding "\r\n" const spacingLength = 2; const data = response.slice(offset, boundaryIndex - spacingLength); + // TODO - extract header data on a per frame basis. + addHeaders(data, headers); // Add the data to the array of results components.push(data); @@ -261,4 +321,5 @@ export { multipartEncode, multipartDecode, guid, + addHeaders, }; From b74f11e94040b903aa9822409fc81c6801086824 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Tue, 17 Jun 2025 10:38:29 -0400 Subject: [PATCH 5/5] fix: Tests had a couple of issues runnning --- dcm4chee-docker-compose.yml | 1 - src/api.js | 24 +++++++++++------------- src/message.js | 2 +- test/test.js | 15 +++++++++++---- test_ci.sh | 2 +- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/dcm4chee-docker-compose.yml b/dcm4chee-docker-compose.yml index 582232d..65d102b 100644 --- a/dcm4chee-docker-compose.yml +++ b/dcm4chee-docker-compose.yml @@ -1,4 +1,3 @@ -version: "3" services: ldap: image: dcm4che/slapd-dcm4chee:2.4.44-13.3 diff --git a/src/api.js b/src/api.js index 40698ed..d3e1d74 100644 --- a/src/api.js +++ b/src/api.js @@ -223,7 +223,7 @@ class DICOMwebClient { let requestInstance = request.instance ? request.instance : new XMLHttpRequest(); requestInstance.open(method, url, true); - if ('responseType' in request) { + if (request.responseType) { requestInstance.responseType = request.responseType; } @@ -297,10 +297,8 @@ class DICOMwebClient { }; // Event triggered while download progresses - if ('progressCallback' in request) { - if (typeof request.progressCallback === 'function') { - requestInstance.onprogress = request.progressCallback; - } + if (typeof request.progressCallback === 'function') { + requestInstance.onprogress = request.progressCallback; } if (requestHooks && areValidRequestHooks(requestHooks)) { @@ -313,13 +311,11 @@ class DICOMwebClient { } // Add withCredentials to request if needed - if ('withCredentials' in request) { - if (request.withCredentials) { - requestInstance.withCredentials = true; - } + if (request.withCredentials) { + requestInstance.withCredentials = true; } - if ('data' in request) { + if (request.data) { requestInstance.send(request.data); } else { requestInstance.send(); @@ -596,6 +592,7 @@ class DICOMwebClient { 'image/gif', 'image/png', 'image/jp2', + 'image/*', ]; } else { supportedMediaTypes = { @@ -610,6 +607,7 @@ class DICOMwebClient { '1.2.840.10008.1.2.4.91': ['image/jp2'], '1.2.840.10008.1.2.4.92': ['image/jpx'], '1.2.840.10008.1.2.4.93': ['image/jpx'], + '*': ['image/*'], }; if (byteRange) { @@ -963,7 +961,7 @@ class DICOMwebClient { }); if( !fieldValueParts.length ) { - throw new Error(`No acceptable media types found among ${JSON.stringify(mediaTypes)}`); + throw new Error(`No acceptable media types found among ${JSON.stringify(mediaTypes)} testing against ${JSON.stringify(acceptableMediaTypes)}`); } return fieldValueParts.join(', '); @@ -1229,7 +1227,7 @@ class DICOMwebClient { debugLog(`retrieve metadata of instance ${options.sopInstanceUID}`); const url = `${this.wadoURL}/studies/${options.studyInstanceUID}/series/${options.seriesInstanceUID}/instances/${options.sopInstanceUID}/metadata`; - const request = getRequestOptions(options.request) + const request = getRequestOptions(options.request); return this._httpGetApplicationJson(url, {}, request); } @@ -1278,6 +1276,7 @@ class DICOMwebClient { const { mediaTypes } = options; const request = getRequestOptions(options.request) + request.responseType = 'arraybuffer'; if (!mediaTypes) { return this._httpGetMultipartApplicationOctetStream( @@ -1319,7 +1318,6 @@ class DICOMwebClient { supportedMediaTypes, ), }; - request.responseType = 'arraybuffer'; return this._httpGet(url, headers, request); } diff --git a/src/message.js b/src/message.js index ccb7224..d7cfac7 100644 --- a/src/message.js +++ b/src/message.js @@ -209,7 +209,7 @@ function addHeaders(destination, headerString) { } if (name === 'content-type') { const endSimpleType = value.indexOf(';'); - contentType ||= value.substring( + contentType = value.substring( 0, endSimpleType === -1 ? value.length : endSimpleType, ); diff --git a/test/test.js b/test/test.js index 3a8fc1e..0b2460a 100644 --- a/test/test.js +++ b/test/test.js @@ -24,6 +24,7 @@ let dwc = new DICOMwebClient.api.DICOMwebClient({ url: 'http://localhost:8008/dcm4chee-arc/aets/DCM4CHEE/rs', retrieveRendered: false, }); + describe('dicomweb.api.DICOMwebClient', function() { // // Note: you can add the following for debugging tests locally @@ -124,10 +125,17 @@ describe('dicomweb.api.DICOMwebClient', function() { sopInstanceUID: '1.3.6.1.4.1.14519.5.2.1.2744.7002.325971588264730726076978589153', frameNumbers: '1', + // The next line should work, but the server side is broken + // mediaTypes: [ {mediaType: 'image/*' }], }; - const frames = dwc.retrieveInstance(options); - }); + const frames = await dwc.retrieveInstanceFrames(options); + expect(frames instanceof Array).toBe(true); + expect(frames.length).toBe(1); + expect(frames[0].contentType).toBe("application/octet-stream"); + // The next line is the correct value for servers supporting image/* + //expect(frames[0].transferSyntaxUID).toBe('1.2.3'); + }, 15000); it('should retrieve a single instance', async function() { // from sample.dcm @@ -173,10 +181,9 @@ describe('dicomweb.api.DICOMwebClient', function() { const options = { studyInstanceUID: '999.999.3859744', seriesInstanceUID: '999.999.94827453', - sopInstanceUID: '999.999.133.1996.1.1800.1.6.25', }; - const metadata = await dwc.retrieveInstanceMetadata(options); + const metadata = await dwc.retrieveSeriesMetadata(options); // TODO: Check why metadata is an array of objects, not just an object const bulkDataOptions = { diff --git a/test_ci.sh b/test_ci.sh index be25fde..6e56811 100755 --- a/test_ci.sh +++ b/test_ci.sh @@ -1,5 +1,5 @@ # Clear any previous data from the last test run -rm -rf /tmp/dcm4chee-arc/db +rm -rf ./tmp/dcm4chee-arc/db # now start dcm4chee archive and wait for it to startup echo 'Starting dcm4chee Docker container'