Skip to content

Commit e03be5a

Browse files
hackermdhackermd
andauthored
Fix(headers): allowed media types for retrieval of frames (#46)
* Allow accept header field with mixed media types This enables request of compressed or uncompressed frames * Fix coding style issues * Increase package version Co-authored-by: hackermd <[email protected]>
1 parent a685624 commit e03be5a

File tree

2 files changed

+146
-52
lines changed

2 files changed

+146
-52
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dicomweb-client",
3-
"version": "0.8.2",
3+
"version": "0.8.3",
44
"description": "Implementation of DICOMweb client code",
55
"main": "build/dicomweb-client.js",
66
"module": "build/dicomweb-client.es.js",

src/api.js

Lines changed: 145 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ function isEmptyObject(obj) {
1010

1111
function areValidRequestHooks(requestHooks) {
1212
const isValid = Array.isArray(requestHooks) && requestHooks.every(requestHook =>
13-
typeof requestHook === 'function'
14-
&& requestHook.length === 2
13+
typeof requestHook === 'function'
14+
&& requestHook.length === 2
1515
);
1616

1717
if (!isValid) {
18-
console.warn('Request hooks should have the following signature: function requestHook(request, metadata) { return request; }');
18+
console.warn(
19+
'Request hooks should have the following signature: ' +
20+
'function requestHook(request, metadata) { return request; }'
21+
);
1922
}
2023

2124
return isValid;
@@ -884,42 +887,54 @@ class DICOMwebClient {
884887
return "bytes=0-";
885888
}
886889

890+
/**
891+
* Gets types that are shared among acceptable media types.
892+
*
893+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
894+
corresponding transfer syntaxes
895+
* @private
896+
* @returns {String[]} Types that are shared among acceptable media types
897+
*/
898+
static _getSharedMediaTypes(mediaTypes) {
899+
const types = new Set();
900+
901+
if (!mediaTypes || !mediaTypes.length) {
902+
return types
903+
}
904+
905+
mediaTypes.forEach(item => {
906+
const { mediaType } = item;
907+
const type = DICOMwebClient._parseMediaType(mediaType)[0];
908+
types.add(`${type}/`);
909+
});
910+
911+
return Array.from(types)
912+
}
913+
887914
/**
888915
* Gets common type of acceptable media types and asserts that only
889916
one type is specified. For example, ``("image/jpeg", "image/jp2")``
890917
will pass, but ``("image/jpeg", "video/mpeg2")`` will raise an
891918
exception.
892919
*
893-
* @param {String[]} mediaTypes - Acceptable media types and optionally the UIDs of the
920+
* @param {Object[]} mediaTypes - Acceptable media types and optionally the UIDs of the
894921
corresponding transfer syntaxes
895922
* @private
896-
* @returns {Array} Common media type
923+
* @returns {String[]} Common media type
897924
*/
898925
static _getCommonMediaType(mediaTypes) {
899926
if (!mediaTypes || !mediaTypes.length) {
900927
throw new Error("No acceptable media types provided");
901928
}
902929

903-
const commonMediaTypes = new Set();
904-
mediaTypes.forEach(item => {
905-
const { mediaType } = item;
906-
907-
if (mediaType.startsWith("application")) {
908-
commonMediaTypes.add(mediaType);
909-
} else {
910-
const type = DICOMwebClient._parseMediaType(mediaType)[0];
911-
912-
commonMediaTypes.add(`${type}/`);
913-
}
914-
});
915-
916-
if (commonMediaTypes.size === 0) {
930+
const sharedMediaTypes = DICOMwebClient._getSharedMediaTypes(mediaTypes);
931+
if (sharedMediaTypes.length === 0) {
917932
throw new Error("No common acceptable media type could be identified.");
918-
} else if (commonMediaTypes.size > 1) {
933+
} else if (sharedMediaTypes.length > 1) {
919934
throw new Error("Acceptable media types must have the same type.");
920935
}
921936

922-
return Array.from(commonMediaTypes)[0];
937+
return sharedMediaTypes[0];
923938
}
924939

925940
/**
@@ -1190,24 +1205,65 @@ class DICOMwebClient {
11901205
withCredentials = options.withCredentials;
11911206
}
11921207
}
1193-
1208+
11941209
let progressCallback = false;
11951210
if ("progressCallback" in options) {
11961211
progressCallback = options.progressCallback;
11971212
}
11981213

11991214
if (!mediaTypes) {
1200-
return this._httpGetMultipartApplicationOctetStream(url, false, false, false, progressCallback, withCredentials);
1215+
return this._httpGetMultipartApplicationOctetStream(
1216+
url, false, false, false, progressCallback, withCredentials
1217+
);
1218+
}
1219+
1220+
const sharedMediaTypes = DICOMwebClient._getSharedMediaTypes(mediaTypes);
1221+
if (sharedMediaTypes.length > 1) {
1222+
/**
1223+
* Enable request of frames that are stored either compressed
1224+
* (image/* media type) or uncompressed (application/octet-stream
1225+
* media type).
1226+
*/
1227+
const supportedMediaTypes = {
1228+
"1.2.840.10008.1.2.1": ["application/octet-stream"],
1229+
"1.2.840.10008.1.2.5": ["image/x-dicom-rle"],
1230+
"1.2.840.10008.1.2.4.50": ["image/jpeg"],
1231+
"1.2.840.10008.1.2.4.51": ["image/jpeg"],
1232+
"1.2.840.10008.1.2.4.57": ["image/jpeg"],
1233+
"1.2.840.10008.1.2.4.70": ["image/jpeg"],
1234+
"1.2.840.10008.1.2.4.80": ["image/x-jls", "image/jls"],
1235+
"1.2.840.10008.1.2.4.81": ["image/x-jls", "image/jls"],
1236+
"1.2.840.10008.1.2.4.90": ["image/jp2"],
1237+
"1.2.840.10008.1.2.4.91": ["image/jp2"],
1238+
"1.2.840.10008.1.2.4.92": ["image/jpx"],
1239+
"1.2.840.10008.1.2.4.93": ["image/jpx"],
1240+
}
1241+
1242+
const headers = {
1243+
Accept: DICOMwebClient._buildMultipartAcceptHeaderFieldValue(
1244+
mediaTypes,
1245+
supportedMediaTypes
1246+
)
1247+
}
1248+
return this._httpGet(
1249+
url, headers, "arraybuffer", progressCallback, withCredentials
1250+
).then(multipartDecode);
12011251
}
12021252

12031253
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
12041254

12051255
if (commonMediaType === MEDIATYPES.OCTET_STREAM) {
1206-
return this._httpGetMultipartApplicationOctetStream(url, mediaTypes, false, false, progressCallback, withCredentials);
1256+
return this._httpGetMultipartApplicationOctetStream(
1257+
url, mediaTypes, false, false, progressCallback, withCredentials
1258+
);
12071259
} else if (commonMediaType.startsWith("image")) {
1208-
return this._httpGetMultipartImage(url, mediaTypes, false, false, false, progressCallback, withCredentials);
1260+
return this._httpGetMultipartImage(
1261+
url, mediaTypes, false, false, false, progressCallback, withCredentials
1262+
);
12091263
} else if (commonMediaType.startsWith("video")) {
1210-
return this._httpGetMultipartVideo(url, mediaTypes, false, false, false, progressCallback, withCredentials);
1264+
return this._httpGetMultipartVideo(
1265+
url, mediaTypes, false, false, false, progressCallback, withCredentials
1266+
);
12111267
}
12121268

12131269
throw new Error(
@@ -1271,17 +1327,26 @@ class DICOMwebClient {
12711327

12721328
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
12731329
if (commonMediaType.startsWith("image")) {
1274-
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
1330+
return this._httpGetImage(
1331+
url, mediaTypes, queryParams, progressCallback, withCredentials
1332+
);
12751333
} else if (commonMediaType.startsWith("video")) {
1276-
return this._httpGetVideo(url, mediaTypes, queryParams, progressCallback, withCredentials);
1334+
return this._httpGetVideo(
1335+
url, mediaTypes, queryParams, progressCallback, withCredentials
1336+
);
12771337
} else if (commonMediaType.startsWith("text")) {
1278-
return this._httpGetText(url, mediaTypes, queryParams, progressCallback, withCredentials);
1338+
return this._httpGetText(
1339+
url, mediaTypes, queryParams, progressCallback, withCredentials
1340+
);
12791341
} else if (commonMediaType === MEDIATYPES.PDF) {
1280-
return this._httpGetApplicationPdf(url, queryParams, progressCallback, withCredentials);
1342+
return this._httpGetApplicationPdf(
1343+
url, queryParams, progressCallback, withCredentials
1344+
);
12811345
}
12821346

12831347
throw new Error(
1284-
`Media type ${commonMediaType} is not supported for retrieval of rendered instance.`
1348+
`Media type ${commonMediaType} is not supported ` +
1349+
'for retrieval of rendered instance.'
12851350
);
12861351
}
12871352

@@ -1336,16 +1401,21 @@ class DICOMwebClient {
13361401
if (queryParams) {
13371402
url += DICOMwebClient._parseQueryParameters(queryParams);
13381403
}
1339-
return this._httpGet(url, headers, responseType, progressCallback, withCredentials);
1404+
return this._httpGet(
1405+
url, headers, responseType, progressCallback, withCredentials
1406+
);
13401407
}
13411408

13421409
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
13431410
if (commonMediaType.startsWith("image")) {
1344-
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
1411+
return this._httpGetImage(
1412+
url, mediaTypes, queryParams, progressCallback, withCredentials
1413+
);
13451414
}
13461415

13471416
throw new Error(
1348-
`Media type ${commonMediaType} is not supported for retrieval of rendered instance.`
1417+
`Media type ${commonMediaType} is not supported ` +
1418+
'for retrieval of rendered instance.'
13491419
);
13501420
}
13511421

@@ -1417,13 +1487,18 @@ class DICOMwebClient {
14171487

14181488
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
14191489
if (commonMediaType.startsWith("image")) {
1420-
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
1490+
return this._httpGetImage(
1491+
url, mediaTypes, queryParams, progressCallback, withCredentials
1492+
);
14211493
} else if (commonMediaType.startsWith("video")) {
1422-
return this._httpGetVideo(url, mediaTypes, queryParams, progressCallback, withCredentials);
1494+
return this._httpGetVideo(
1495+
url, mediaTypes, queryParams, progressCallback, withCredentials
1496+
);
14231497
}
14241498

14251499
throw new Error(
1426-
`Media type ${commonMediaType} is not supported for retrieval of rendered frame.`
1500+
`Media type ${commonMediaType} is not supported ` +
1501+
'for retrieval of rendered frame.'
14271502
);
14281503
}
14291504

@@ -1490,16 +1565,21 @@ class DICOMwebClient {
14901565
if (queryParams) {
14911566
url += DICOMwebClient._parseQueryParameters(queryParams);
14921567
}
1493-
return this._httpGet(url, headers, responseType, progressCallback, withCredentials);
1568+
return this._httpGet(
1569+
url, headers, responseType, progressCallback, withCredentials
1570+
);
14941571
}
14951572

14961573
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
14971574
if (commonMediaType.startsWith("image")) {
1498-
return this._httpGetImage(url, mediaTypes, queryParams, progressCallback, withCredentials);
1575+
return this._httpGetImage(
1576+
url, mediaTypes, queryParams, progressCallback, withCredentials
1577+
);
14991578
}
15001579

15011580
throw new Error(
1502-
`Media type ${commonMediaType} is not supported for retrieval of rendered frame.`
1581+
`Media type ${commonMediaType} is not supported ` +
1582+
'for retrieval of rendered frame.'
15031583
);
15041584
}
15051585

@@ -1540,14 +1620,16 @@ class DICOMwebClient {
15401620
}
15411621

15421622
if (!mediaTypes) {
1543-
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials).then(getFirstResult);
1623+
return this._httpGetMultipartApplicationDicom(
1624+
url, false, false, progressCallback, withCredentials
1625+
).then(getFirstResult);
15441626
}
15451627

15461628
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
15471629
if (commonMediaType === MEDIATYPES.DICOM) {
1548-
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials).then(
1549-
getFirstResult
1550-
);
1630+
return this._httpGetMultipartApplicationDicom(
1631+
url, mediaTypes, false, progressCallback, withCredentials
1632+
).then(getFirstResult);
15511633
}
15521634

15531635
throw new Error(
@@ -1589,12 +1671,16 @@ class DICOMwebClient {
15891671
}
15901672

15911673
if (!mediaTypes) {
1592-
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials);
1674+
return this._httpGetMultipartApplicationDicom(
1675+
url, false, false, progressCallback, withCredentials
1676+
);
15931677
}
15941678

15951679
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
15961680
if (commonMediaType === MEDIATYPES.DICOM) {
1597-
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials);
1681+
return this._httpGetMultipartApplicationDicom(
1682+
url, mediaTypes, false, progressCallback, withCredentials
1683+
);
15981684
}
15991685

16001686
throw new Error(
@@ -1628,14 +1714,18 @@ class DICOMwebClient {
16281714
if ("progressCallback" in options) {
16291715
progressCallback = options.progressCallback;
16301716
}
1631-
1717+
16321718
if (!mediaTypes) {
1633-
return this._httpGetMultipartApplicationDicom(url, false, false, progressCallback, withCredentials);
1719+
return this._httpGetMultipartApplicationDicom(
1720+
url, false, false, progressCallback, withCredentials
1721+
);
16341722
}
16351723

16361724
const commonMediaType = DICOMwebClient._getCommonMediaType(mediaTypes);
16371725
if (commonMediaType === MEDIATYPES.DICOM) {
1638-
return this._httpGetMultipartApplicationDicom(url, mediaTypes, false, progressCallback, withCredentials);
1726+
return this._httpGetMultipartApplicationDicom(
1727+
url, mediaTypes, false, progressCallback, withCredentials
1728+
);
16391729
}
16401730

16411731
throw new Error(
@@ -1692,7 +1782,9 @@ class DICOMwebClient {
16921782
false, progressCallback, withCredentials
16931783
);
16941784
} else if (commonMediaType.startsWith("image")) {
1695-
return this._httpGetMultipartImage(url, mediaTypes, byteRange, false, false, progressCallback, withCredentials);
1785+
return this._httpGetMultipartImage(
1786+
url, mediaTypes, byteRange, false, false, progressCallback, withCredentials
1787+
);
16961788
}
16971789

16981790
throw new Error(
@@ -1728,7 +1820,9 @@ class DICOMwebClient {
17281820
withCredentials = options.withCredentials;
17291821
}
17301822
}
1731-
return this._httpPost(url, headers, data, options.progressCallback, withCredentials);
1823+
return this._httpPost(
1824+
url, headers, data, options.progressCallback, withCredentials
1825+
);
17321826
}
17331827
}
17341828

0 commit comments

Comments
 (0)