feat(proxy datasource): JSON server configuration launch (#2791)

* feat: delegating dicom web proxy datasource

* fix: configurably allow WADO image loader to issue preflight OPTIONS request

* Added documentation and fixed up some error handling from PR review

* review comments changes

* another small code review fix
This commit is contained in:
David Smith 2023-05-01 12:58:53 -04:00 committed by GitHub
parent b5b936b53e
commit 0e3491d6bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 152 additions and 0 deletions

View File

@ -0,0 +1,84 @@
import { IWebApiDataSource } from '@ohif/core';
import { createDicomWebApi } from '../DicomWebDataSource/index';
/**
* This datasource is initialized with a url that returns a JSON object with a
* dicomWeb datasource configuration array present in a "servers" object.
*
* Only the first array item is parsed, if there are multiple items in the
* dicomWeb configuration array
*
*/
function createDicomWebProxyApi(
dicomWebProxyConfig,
UserAuthenticationService
) {
const { name } = dicomWebProxyConfig;
let dicomWebDelegate = undefined;
const implementation = {
initialize: async ({ params, query }) => {
let studyInstanceUIDs = [];
// there seem to be a couple of variations of the case for this parameter
const queryStudyInstanceUIDs =
query.get('studyInstanceUIDs') || query.get('studyInstanceUids');
if (!queryStudyInstanceUIDs) {
throw new Error(`No studyInstanceUids in request for '${name}'`);
}
const url = query.get('url');
if (!url) {
throw new Error(`No url for '${name}'`);
} else {
const response = await fetch(url);
let data = await response.json();
if (!data.servers?.dicomWeb?.[0]) {
throw new Error('Invalid configuration returned by url');
}
dicomWebDelegate = createDicomWebApi(
data.servers.dicomWeb[0],
UserAuthenticationService
);
studyInstanceUIDs = queryStudyInstanceUIDs.split(';');
}
return studyInstanceUIDs;
},
query: {
studies: {
search: params => dicomWebDelegate.query.studies.search(params),
},
series: {
search: (...args) => dicomWebDelegate.query.series.search(...args),
},
instances: {
search: (studyInstanceUid, queryParameters) =>
dicomWebDelegate.query.instances.search(
studyInstanceUid,
queryParameters
),
},
},
retrieve: {
directURL: (...args) => dicomWebDelegate.retrieve.directURL(...args),
series: {
metadata: (...args) =>
dicomWebDelegate.retrieve.series.metadata(...args),
},
},
store: {
dicom: (...args) => dicomWebDelegate.store(...args),
},
deleteStudyMetadataPromise: (...args) =>
dicomWebDelegate.deleteStudyMetadataPromise(...args),
getImageIdsForDisplaySet: (...args) =>
dicomWebDelegate.getImageIdsForDisplaySet(...args),
getImageIdsForInstance: (...args) =>
dicomWebDelegate.getImageIdsForInstance(...args),
};
return IWebApiDataSource.create(implementation);
}
export { createDicomWebProxyApi };

View File

@ -5,6 +5,7 @@
import { createDicomWebApi } from './DicomWebDataSource/index.js';
import { createDicomJSONApi } from './DicomJSONDataSource/index.js';
import { createDicomLocalApi } from './DicomLocalDataSource/index.js';
import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js';
/**
*
@ -16,6 +17,11 @@ function getDataSourcesModule() {
type: 'webApi',
createDataSource: createDicomWebApi,
},
{
name: 'dicomwebproxy',
type: 'webApi',
createDataSource: createDicomWebProxyApi,
},
{
name: 'dicomjson',
type: 'jsonApi',

View File

@ -0,0 +1,54 @@
---
sidebar_position: 4
sidebar_label: DICOMweb Proxy
---
# DICOMweb Proxy
You can launch the OHIF Viewer with a url that returns a JSON file which
contains a DICOMWeb configuration. The DICOMweb Proxy constructs a DICOMweb
datasource and delegates subsequent requests for metadata and images to that.
Usage is similar to that of the [DICOM JSON](./dicom-json.md) datasource and
might look like
`https://v3-demo.ohif.org/viewer/dicomwebproxy?url=https://ohif-dicom-json-example.s3.amazonaws.com/dicomweb.json`
The url to the location of the JSON file is passed in the query
after the `dicomwebproxy` string, which is
`https://ohif-dicom-json-example.s3.amazonaws.com/dicomweb.json` (this json file
does not exist at the moment of this writing).
## DICOMweb JSON configuration sample
The json returned by the url in this example contains a dicomweb configuration
(see [DICOMweb](dicom-web.md)), in a "servers" object, which is then used to
construct a dynamic DICOMweb datasource to delegate requests to. Here is an
example configuration that might be returned using the url parameter.
```json
{
"servers": {
"dicomWeb": [
{
"name": "DCM4CHEE",
"wadoUriRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado",
"qidoRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs",
"wadoRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs",
"qidoSupportsIncludeField": true,
"supportsReject": true,
"imageRendering": "wadors",
"thumbnailRendering": "wadors",
"enableStudyLazyLoad": true,
"supportsFuzzyMatching": true,
"supportsWildcard": true
}
]
}
}
```
The DICOMweb Proxy expects the json returned by the url parameter it is invoked
with to include a servers object which contains a "dicomWeb" configuration array
as above. It will only consider the first array item in the dicomWeb
configuration.

View File

@ -53,6 +53,14 @@ window.config = {
useBulkDataURI: false,
},
},
{
friendlyName: 'dicomweb delegating proxy',
namespace: '@ohif/extension-default.dataSourcesModule.dicomwebproxy',
sourceName: 'dicomwebproxy',
configuration: {
name: 'dicomwebproxy',
},
},
{
friendlyName: 'dicom json',
namespace: '@ohif/extension-default.dataSourcesModule.dicomjson',