@@ -37,6 +37,12 @@ const MEDIATYPES = {
3737 PNG : 'image/png' ,
3838} ;
3939
40+ /**
41+ * debugLog is a function that can be called with console.log arguments, and will
42+ * be conditionally displayed, only when debug logging is enabled.
43+ */
44+ let debugLog = ( ) => { } ;
45+
4046/**
4147 * @typedef { import("../types/types").InstanceMetadata } InstanceMetadata
4248 */
@@ -66,6 +72,7 @@ class DICOMwebClient {
6672 * @param {Object= } options.headers - HTTP headers
6773 * @param {Array.<RequestHook>= } options.requestHooks - Request hooks.
6874 * @param {Object= } options.verbose - print to console request warnings and errors, default true
75+ * @param {Object= } options.debug - print to the console debug level information/status updates.
6976 * @param {boolean|String } options.singlepart - retrieve singlepart for the named types.
7077 * The available types are: bulkdata, video, image. true means all.
7178 */
@@ -86,28 +93,28 @@ class DICOMwebClient {
8693 }
8794
8895 if ( 'qidoURLPrefix' in options ) {
89- console . log ( `use URL prefix for QIDO-RS: ${ options . qidoURLPrefix } ` ) ;
96+ debugLog ( `use URL prefix for QIDO-RS: ${ options . qidoURLPrefix } ` ) ;
9097 this . qidoURL = `${ this . baseURL } /${ options . qidoURLPrefix } ` ;
9198 } else {
9299 this . qidoURL = this . baseURL ;
93100 }
94101
95102 if ( 'wadoURLPrefix' in options ) {
96- console . log ( `use URL prefix for WADO-RS: ${ options . wadoURLPrefix } ` ) ;
103+ debugLog ( `use URL prefix for WADO-RS: ${ options . wadoURLPrefix } ` ) ;
97104 this . wadoURL = `${ this . baseURL } /${ options . wadoURLPrefix } ` ;
98105 } else {
99106 this . wadoURL = this . baseURL ;
100107 }
101108
102109 if ( 'stowURLPrefix' in options ) {
103- console . log ( `use URL prefix for STOW-RS: ${ options . stowURLPrefix } ` ) ;
110+ debugLog ( `use URL prefix for STOW-RS: ${ options . stowURLPrefix } ` ) ;
104111 this . stowURL = `${ this . baseURL } /${ options . stowURLPrefix } ` ;
105112 } else {
106113 this . stowURL = this . baseURL ;
107114 }
108115
109116 if ( options . singlepart ) {
110- console . log ( 'use singlepart' , options . singlepart ) ;
117+ debugLog ( 'use singlepart' , options . singlepart ) ;
111118 this . singlepart = options . singlepart === true ? 'bulkdata,video,image' : options . singlepart ;
112119 } else {
113120 this . singlepart = '' ;
@@ -125,8 +132,33 @@ class DICOMwebClient {
125132
126133 // Verbose - print to console request warnings and errors, default true
127134 this . verbose = options . verbose !== false ;
135+
136+ this . setDebug ( options . debug ) ;
137+
138+
139+ }
140+
141+ /**
142+ * Allows setting the debug log information.
143+ * Note this is different from verbose in that verbose is whether to include warning/error information, defaulting to true
144+ *
145+ * @param {boolean } debugLevel
146+ * @param {function } debugLogFunction to call with the debug output arguments.
147+ */
148+ setDebug ( debugLevel = false , debugLogFunction = null ) {
149+ this . debugLevel = ! ! debugLevel ;
150+ debugLog = debugLogFunction || debugLevel ? console . log : ( ) => { } ;
128151 }
129152
153+ /**
154+ * Gets debug flag
155+ *
156+ * @returns true if debug logging is enabled
157+ */
158+ getDebug ( ) {
159+ return this . debugLevel ;
160+ }
161+
130162 /**
131163 * Sets verbose flag.
132164 *
@@ -194,12 +226,12 @@ class DICOMwebClient {
194226
195227 // Event triggered when upload starts
196228 request . onloadstart = function onloadstart ( ) {
197- // console.log ('upload started: ', url)
229+ debugLog ( 'upload started: ' , url )
198230 } ;
199231
200232 // Event triggered when upload ends
201233 request . onloadend = function onloadend ( ) {
202- // console.log ('upload finished')
234+ debugLog ( 'upload finished' )
203235 } ;
204236
205237 // Handle response message
@@ -699,7 +731,8 @@ class DICOMwebClient {
699731
700732 /**
701733 * Performs an HTTP GET request that accepts a multipart message
702- * with a application/octet-stream media type.
734+ * with a application/octet-stream, OR any of the equivalencies for that (eg
735+ * application/pdf etc)
703736 *
704737 * @param {String } url - Unique resource locator
705738 * @param {Object[] } mediaTypes - Acceptable media types and optionally the UIDs of the
@@ -721,7 +754,7 @@ class DICOMwebClient {
721754 const headers = { } ;
722755 const defaultMediaType = 'application/octet-stream' ;
723756 const supportedMediaTypes = {
724- '1.2.840.10008.1.2.1' : [ defaultMediaType ] ,
757+ '1.2.840.10008.1.2.1' : [ ... Object . values ( MEDIATYPES ) ] ,
725758 } ;
726759
727760 let acceptableMediaTypes = mediaTypes ;
@@ -826,13 +859,16 @@ class DICOMwebClient {
826859 }
827860
828861 /**
829- * Builds an accept header field value for HTTP GET multipart request
830- messages.
831- *
832- * @param {Object[] } mediaTypes - Acceptable media types
833- * @param {Object[] } supportedMediaTypes - Supported media types
834- * @private
835- */
862+ * Builds an accept header field value for HTTP GET multipart request
863+ * messages. Will throw an exception if no media types are found which are acceptable,
864+ * but will only log a verbose level message when types are specified which are
865+ * not acceptable. This allows requesting several types with having to know
866+ * whether they are all acceptable or not.
867+ *
868+ * @param {Object[] } mediaTypes - Acceptable media types
869+ * @param {Object[] } supportedMediaTypes - Supported media types
870+ * @private
871+ */
836872 static _buildMultipartAcceptHeaderFieldValue (
837873 mediaTypes ,
838874 supportedMediaTypes ,
@@ -863,9 +899,10 @@ class DICOMwebClient {
863899 . includes ( mediaType )
864900 ) {
865901 if ( ! mediaType . endsWith ( '/*' ) || ! mediaType . endsWith ( '/' ) ) {
866- throw new Error (
902+ debugLog (
867903 `Media type ${ mediaType } is not supported for requested resource` ,
868904 ) ;
905+ return ;
869906 }
870907 }
871908
@@ -907,14 +944,21 @@ class DICOMwebClient {
907944 Array . isArray ( supportedMediaTypes ) &&
908945 ! supportedMediaTypes . includes ( mediaType )
909946 ) {
910- throw new Error (
911- `Media type ${ mediaType } is not supported for requested resource` ,
912- ) ;
947+ if ( this . verbose ) {
948+ console . warn (
949+ `Media type ${ mediaType } is not supported for requested resource` ,
950+ ) ;
951+ }
952+ return ;
913953 }
914954
915955 fieldValueParts . push ( fieldValue ) ;
916956 } ) ;
917957
958+ if ( ! fieldValueParts . length ) {
959+ throw new Error ( `No acceptable media types found among ${ JSON . stringify ( mediaTypes ) } ` ) ;
960+ }
961+
918962 return fieldValueParts . join ( ', ' ) ;
919963 }
920964
@@ -961,15 +1005,15 @@ class DICOMwebClient {
9611005 }
9621006
9631007 /**
964- * Gets common type of acceptable media types and asserts that only
1008+ * Gets common base type of acceptable media types and asserts that only
9651009 one type is specified. For example, ``("image/jpeg", "image/jp2")``
9661010 will pass, but ``("image/jpeg", "video/mpeg2")`` will raise an
9671011 exception.
9681012 *
9691013 * @param {Object[] } mediaTypes - Acceptable media types and optionally the UIDs of the
9701014 corresponding transfer syntaxes
9711015 * @private
972- * @returns {String[] } Common media type
1016+ * @returns {String[] } Common media type, eg `image/` for the above example.
9731017 */
9741018 static _getCommonMediaType ( mediaTypes ) {
9751019 if ( ! mediaTypes || ! mediaTypes . length ) {
@@ -994,7 +1038,7 @@ class DICOMwebClient {
9941038 * @return {Object[] } Study representations (http://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_6.7.html#table_6.7.1-2)
9951039 */
9961040 searchForStudies ( options = { } ) {
997- console . log ( 'search for studies' ) ;
1041+ debugLog ( 'search for studies' ) ;
9981042 let withCredentials = false ;
9991043 let url = `${ this . qidoURL } /studies` ;
10001044 if ( 'queryParams' in options ) {
@@ -1022,7 +1066,7 @@ class DICOMwebClient {
10221066 'Study Instance UID is required for retrieval of study metadata' ,
10231067 ) ;
10241068 }
1025- console . log ( `retrieve metadata of study ${ options . studyInstanceUID } ` ) ;
1069+ debugLog ( `retrieve metadata of study ${ options . studyInstanceUID } ` ) ;
10261070 const url = `${ this . wadoURL } /studies/${ options . studyInstanceUID } /metadata` ;
10271071 let withCredentials = false ;
10281072 if ( 'withCredentials' in options ) {
@@ -1044,7 +1088,7 @@ class DICOMwebClient {
10441088 searchForSeries ( options = { } ) {
10451089 let url = this . qidoURL ;
10461090 if ( 'studyInstanceUID' in options ) {
1047- console . log ( `search series of study ${ options . studyInstanceUID } ` ) ;
1091+ debugLog ( `search series of study ${ options . studyInstanceUID } ` ) ;
10481092 url += `/studies/${ options . studyInstanceUID } ` ;
10491093 }
10501094 url += '/series' ;
@@ -1081,7 +1125,7 @@ class DICOMwebClient {
10811125 ) ;
10821126 }
10831127
1084- console . log ( `retrieve metadata of series ${ options . seriesInstanceUID } ` ) ;
1128+ debugLog ( `retrieve metadata of series ${ options . seriesInstanceUID } ` ) ;
10851129 const url = `${ this . wadoURL } /studies/${ options . studyInstanceUID } /series/${ options . seriesInstanceUID } /metadata` ;
10861130 let withCredentials = false ;
10871131 if ( 'withCredentials' in options ) {
@@ -1107,17 +1151,17 @@ class DICOMwebClient {
11071151 if ( 'studyInstanceUID' in options ) {
11081152 url += `/studies/${ options . studyInstanceUID } ` ;
11091153 if ( 'seriesInstanceUID' in options ) {
1110- console . log (
1154+ debugLog (
11111155 `search for instances of series ${ options . seriesInstanceUID } ` ,
11121156 ) ;
11131157 url += `/series/${ options . seriesInstanceUID } ` ;
11141158 } else {
1115- console . log (
1159+ debugLog (
11161160 `search for instances of study ${ options . studyInstanceUID } ` ,
11171161 ) ;
11181162 }
11191163 } else {
1120- console . log ( 'search for instances' ) ;
1164+ debugLog ( 'search for instances' ) ;
11211165 }
11221166 url += '/instances' ;
11231167 if ( 'queryParams' in options ) {
@@ -1191,7 +1235,7 @@ class DICOMwebClient {
11911235 'SOP Instance UID is required for retrieval of instance metadata' ,
11921236 ) ;
11931237 }
1194- console . log ( `retrieve metadata of instance ${ options . sopInstanceUID } ` ) ;
1238+ debugLog ( `retrieve metadata of instance ${ options . sopInstanceUID } ` ) ;
11951239 const url = `${ this . wadoURL } /studies/${ options . studyInstanceUID } /series/${ options . seriesInstanceUID } /instances/${ options . sopInstanceUID } /metadata` ;
11961240 let withCredentials = false ;
11971241 if ( 'withCredentials' in options ) {
@@ -1232,7 +1276,7 @@ class DICOMwebClient {
12321276 'frame numbers are required for retrieval of instance frames' ,
12331277 ) ;
12341278 }
1235- console . log (
1279+ debugLog (
12361280 `retrieve frames ${ options . frameNumbers . toString ( ) } of instance ${
12371281 options . sopInstanceUID
12381282 } `,
@@ -1287,6 +1331,8 @@ class DICOMwebClient {
12871331 '1.2.840.10008.1.2.4.91' : [ 'image/jp2' ] ,
12881332 '1.2.840.10008.1.2.4.92' : [ 'image/jpx' ] ,
12891333 '1.2.840.10008.1.2.4.93' : [ 'image/jpx' ] ,
1334+ '1.2.840.10008.1.2.4.201' : [ 'image/jhc' ] ,
1335+ '1.2.840.10008.1.2.4.202' : [ 'image/jhc' ] ,
12901336 } ;
12911337
12921338 const headers = {
@@ -1554,7 +1600,7 @@ class DICOMwebClient {
15541600 ) ;
15551601 }
15561602
1557- console . debug (
1603+ debugLog (
15581604 `retrieve rendered frames ${ options . frameNumbers . toString ( ) } of instance ${
15591605 options . sopInstanceUID
15601606 } `,
@@ -1881,43 +1927,34 @@ class DICOMwebClient {
18811927 return this . _httpGet ( url , options . headers , 'arraybuffer' , null , withCredentials ) ;
18821928 }
18831929
1884- if ( ! mediaTypes ) {
1885- return this . _httpGetMultipartApplicationOctetStream (
1886- url ,
1887- mediaTypes ,
1888- byteRange ,
1889- false ,
1890- false ,
1891- withCredentials ,
1892- ) ;
1893- }
1894-
1895- const commonMediaType = DICOMwebClient . _getCommonMediaType ( mediaTypes ) ;
1896-
1897- if ( commonMediaType === MEDIATYPES . OCTET_STREAM ) {
1898- return this . _httpGetMultipartApplicationOctetStream (
1899- url ,
1900- mediaTypes ,
1901- byteRange ,
1902- false ,
1903- progressCallback ,
1904- withCredentials ,
1905- ) ;
1906- }
1907- if ( commonMediaType . startsWith ( 'image' ) ) {
1908- return this . _httpGetMultipartImage (
1909- url ,
1910- mediaTypes ,
1911- byteRange ,
1912- false ,
1913- false ,
1914- progressCallback ,
1915- withCredentials ,
1916- ) ;
1930+ if ( mediaTypes ) {
1931+ try {
1932+ const commonMediaType = DICOMwebClient . _getCommonMediaType ( mediaTypes ) ;
1933+
1934+ if ( commonMediaType === 'image/' ) {
1935+ return this . _httpGetMultipartImage (
1936+ url ,
1937+ mediaTypes ,
1938+ byteRange ,
1939+ false ,
1940+ false ,
1941+ progressCallback ,
1942+ withCredentials ,
1943+ ) ;
1944+ }
1945+ } catch ( e ) {
1946+ // No-op - this happens sometimes if trying to fetch the specific desired type but want to fallback to octet-stream
1947+ }
19171948 }
19181949
1919- throw new Error (
1920- `Media type ${ commonMediaType } is not supported for retrieval of bulk data.` ,
1950+ // Just use the media types provided
1951+ return this . _httpGetMultipartApplicationOctetStream (
1952+ url ,
1953+ mediaTypes ,
1954+ byteRange ,
1955+ false ,
1956+ progressCallback ,
1957+ withCredentials ,
19211958 ) ;
19221959 }
19231960
@@ -1954,6 +1991,8 @@ class DICOMwebClient {
19541991 options . request ,
19551992 ) ;
19561993 }
1994+
1995+
19571996}
19581997
19591998
0 commit comments