diff --git a/extensions/cornerstone/src/init.tsx b/extensions/cornerstone/src/init.tsx index 4a07f4e63..98f905ab9 100644 --- a/extensions/cornerstone/src/init.tsx +++ b/extensions/cornerstone/src/init.tsx @@ -166,7 +166,7 @@ export default async function init({ prefetch: appConfig?.maxNumRequests?.prefetch || 10, }; - initWADOImageLoader(userAuthenticationService, appConfig); + initWADOImageLoader(userAuthenticationService, appConfig, extensionManager); /* Measurement Service */ this.measurementServiceSource = connectToolsToMeasurementService( diff --git a/extensions/cornerstone/src/initWADOImageLoader.js b/extensions/cornerstone/src/initWADOImageLoader.js index c21326b5f..f5ac1a8ab 100644 --- a/extensions/cornerstone/src/initWADOImageLoader.js +++ b/extensions/cornerstone/src/initWADOImageLoader.js @@ -35,7 +35,8 @@ function initWebWorkers(appConfig) { export default function initWADOImageLoader( userAuthenticationService, - appConfig + appConfig, + extensionManager ) { dicomImageLoader.external.cornerstone = cornerstone; dicomImageLoader.external.dicomParser = dicomParser; @@ -54,6 +55,32 @@ export default function initWADOImageLoader( // we should set this flag to false. convertFloatPixelDataToInt: false, }, + beforeSend: function (xhr) { + const headers = userAuthenticationService.getAuthorizationHeader(); + const sourceConfig = extensionManager.getActiveDataSource()[0].getConfig() + const acceptHeader = generateAcceptHeader(sourceConfig.acceptHeader, sourceConfig.omitQuotationForMultipartRequest) + + // Request: + // JPEG-LS Lossless (1.2.840.10008.1.2.4.80) if available, otherwise accept + // whatever transfer-syntax the origin server provides. + // For now we use image/jls and image/x-jls because some servers still use the old type + // http://dicom.nema.org/medical/dicom/current/output/html/part18.html + const xhrRequestHeaders = { + Accept: acceptHeader + /* + appConfig.omitQuotationForMultipartRequest + ? 'multipart/related; type=application/octet-stream' + : 'multipart/related; type="application/octet-stream"', + // 'multipart/related; type="image/x-jls", multipart/related; type="image/jls"; transfer-syntax="1.2.840.10008.1.2.4.80", multipart/related; type="image/x-jls", multipart/related; type="application/octet-stream"; transfer-syntax=*', + */ + }; + + if (headers) { + Object.assign(xhrRequestHeaders, headers); + } + + return xhrRequestHeaders; + }, errorInterceptor: error => { errorHandler.getHTTPErrorHandler(error); }, @@ -62,6 +89,34 @@ export default function initWADOImageLoader( initWebWorkers(appConfig); } +const generateAcceptHeader = (configAcceptHeader = [], omitQuotationForMultipartRequest = false) => { + let acceptHeader = [] + if (configAcceptHeader.length === 0) { + acceptHeader.push('multipart/related; type=application/octet-stream') + } else { + acceptHeader = configAcceptHeader + } + + if (!omitQuotationForMultipartRequest) { + //need to add quotation for each mime type of each accept entry + acceptHeader = acceptHeader.map(accept => { + let mimes = accept.split("; ") + let newMimes = mimes.map(mime => { + if (mime.startsWith('type=')) { + const quotedParam = 'type=' + '"' + mime.substring(5, mime.length) + '"' + return quotedParam + } else { + return mime + } + }) + return newMimes.join(';') + }) + } + + return acceptHeader + +} + export function destroy() { // Note: we don't want to call .terminate on the webWorkerManager since // that resets the config diff --git a/extensions/default/src/DicomWebDataSource/index.js b/extensions/default/src/DicomWebDataSource/index.js index d1e5ef472..5c31ec042 100644 --- a/extensions/default/src/DicomWebDataSource/index.js +++ b/extensions/default/src/DicomWebDataSource/index.js @@ -66,15 +66,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) { const dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig)); - //If accept header is not specified, set as multipart - let formattedAcceptHeader = acceptHeader ?? [] - if (formattedAcceptHeader.length === 0) { - formattedAcceptHeader = ['multipart/related'] - } - - if (!omitQuotationForMultipartRequest) { - formattedAcceptHeader.forEach((header) => '"' + header + '"') - } + //Generate accept header depending on config params + let formattedAcceptHeader = generateAcceptHeader(acceptHeader, omitQuotationForMultipartRequest) const authHeaders = userAuthenticationService.getAuthorizationHeader() @@ -98,8 +91,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) { singlepart, headers: { ...xhrRequestHeaders, - //Serialize Accept header - Accept: formattedAcceptHeader.join('; ') + Accept: formattedAcceptHeader }, errorInterceptor: errorHandler.getHTTPErrorHandler(), }; @@ -526,4 +518,32 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) { return IWebApiDataSource.create(implementation); } +const generateAcceptHeader = (configAcceptHeader = [], omitQuotationForMultipartRequest = false) => { + let acceptHeader = [] + if (configAcceptHeader.length === 0) { + acceptHeader.push('multipart/related; type=application/octet-stream') + } else { + acceptHeader = configAcceptHeader + } + + if (!omitQuotationForMultipartRequest) { + //need to add quotation for each mime type of each accept entry + acceptHeader = acceptHeader.map(accept => { + let mimes = accept.split("; ") + let newMimes = mimes.map(mime => { + if (mime.startsWith('type=')) { + const quotedParam = 'type=' + '"' + mime.substring(5, mime.length) + '"' + return quotedParam + } else { + return mime + } + }) + return newMimes.join(';') + }) + } + + return acceptHeader + +} + export { createDicomWebApi }; diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md index 5a6f16e55..21239030c 100644 --- a/platform/docs/docs/configuration/configurationFiles.md +++ b/platform/docs/docs/configuration/configurationFiles.md @@ -112,7 +112,7 @@ Here are a list of some options available: - `maxNumberOfWebWorkers`: The maximum number of web workers to use for decoding. Defaults to minimum of `navigator.hardwareConcurrency` and what is specified by `maxNumberOfWebWorkers`. Some windows machines require smaller values. -- `requestTransferSyntaxUID` : Request for a specific TS to the DICOM archive ex : 1.2.840.10008.1.2.4.80 +- `acceptHeader` : accept header to request specific dicom transfer syntax ex : [ 'multipart/related; type=image/jls; q=1', 'multipart/related; type=application/octet-stream; q=0.1' ] - `omitQuotationForMultipartRequest`: Some servers (e.g., .NET) require the `multipart/related` request to be sent without quotation marks. Defaults to `false`. If your server doesn't require this, then setting this flag to `true` might improve performance (by removing the need for preflight requests). Also note that if auth headers are used, a preflight request is required. - `maxNumRequests`: The maximum number of requests to allow in parallel. It is an object with keys of `interaction`, `thumbnail`, and `prefetch`. You can specify a specific number for each type.