@@ -149,7 +149,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
149149 * @return {any } value
150150 */
151151 const getHeaderValue = ( headersObject , name ) => {
152- const asLowercase = name . toLowercase ( ) ;
152+ const asLowercase = name . toLowerCase ( ) ;
153153 return headersObject [ Object . keys ( headersObject ) . find ( k => k . toLowerCase ( ) === asLowercase ) ] ;
154154 }
155155 this . count = 0 ;
@@ -256,34 +256,42 @@ in your Node-RED user directory (${RED.settings.userDir}).
256256 opts . hooks = {
257257 beforeRequest : [
258258 options => {
259- // Whilst HTTP headers are meant to be case-insensitive,
260- // in the real world, there are servers that aren't so compliant.
261- // GOT will lower case all headers given a chance, so we need
262- // to restore the case of any headers the user has set.
263- Object . keys ( options . headers ) . forEach ( h => {
264- if ( originalHeaderMap [ h ] && originalHeaderMap [ h ] !== h ) {
265- options . headers [ originalHeaderMap [ h ] ] = options . headers [ h ] ;
266- delete options . headers [ h ] ;
259+ try {
260+ // Whilst HTTP headers are meant to be case-insensitive,
261+ // in the real world, there are servers that aren't so compliant.
262+ // GOT will lower case all headers given a chance, so we need
263+ // to restore the case of any headers the user has set.
264+ Object . keys ( options . headers ) . forEach ( h => {
265+ if ( originalHeaderMap [ h ] && originalHeaderMap [ h ] !== h ) {
266+ options . headers [ originalHeaderMap [ h ] ] = options . headers [ h ] ;
267+ delete options . headers [ h ] ;
268+ }
269+ } )
270+ if ( node . insecureHTTPParser ) {
271+ // Setting the property under _unixOptions as pretty
272+ // much the only hack available to get got to apply
273+ // a core http option it doesn't think we should be
274+ // allowed to set
275+ options . _unixOptions = { ...options . unixOptions , insecureHTTPParser : true }
267276 }
268- } )
269- if ( node . insecureHTTPParser ) {
270- // Setting the property under _unixOptions as pretty
271- // much the only hack available to get got to apply
272- // a core http option it doesn't think we should be
273- // allowed to set
274- options . _unixOptions = { ...options . unixOptions , insecureHTTPParser : true }
277+ } catch ( err ) {
278+ node . warn ( "Error in beforeRequest hook: " + err . message ) ;
275279 }
276280 }
277281 ] ,
278282 beforeRedirect : [
279283 ( options , response ) => {
280- let redirectInfo = {
281- location : response . headers . location
282- }
283- if ( response . headers . hasOwnProperty ( 'set-cookie' ) ) {
284- redirectInfo . cookies = extractCookies ( response . headers [ 'set-cookie' ] ) ;
284+ try {
285+ let redirectInfo = {
286+ location : response . headers . location
287+ }
288+ if ( response . headers . hasOwnProperty ( 'set-cookie' ) ) {
289+ redirectInfo . cookies = extractCookies ( response . headers [ 'set-cookie' ] ) ;
290+ }
291+ redirectList . push ( redirectInfo )
292+ } catch ( err ) {
293+ node . warn ( "Error processing redirect: " + err . message ) ;
285294 }
286- redirectList . push ( redirectInfo )
287295 }
288296 ]
289297 }
@@ -422,25 +430,30 @@ in your Node-RED user directory (${RED.settings.userDir}).
422430 let digestCreds = this . credentials ;
423431 let sentCreds = false ;
424432 opts . hooks . afterResponse = [ ( response , retry ) => {
425- if ( response . statusCode === 401 ) {
426- if ( sentCreds ) {
427- return response
428- }
429- const requestUrl = new URL ( response . request . requestUrl ) ;
430- const options = { headers : { } }
431- const normalisedHeaders = { } ;
432- Object . keys ( response . headers ) . forEach ( k => {
433- normalisedHeaders [ k . toLowerCase ( ) ] = response . headers [ k ]
434- } )
435- if ( normalisedHeaders [ 'www-authenticate' ] ) {
436- let authHeader = buildDigestHeader ( digestCreds . user , digestCreds . password , response . request . options . method , requestUrl . pathname + requestUrl . search , normalisedHeaders [ 'www-authenticate' ] )
437- options . headers . Authorization = authHeader ;
433+ try {
434+ if ( response . statusCode === 401 ) {
435+ if ( sentCreds ) {
436+ return response
437+ }
438+ const requestUrl = new URL ( response . request . requestUrl ) ;
439+ const options = { headers : { } }
440+ const normalisedHeaders = { } ;
441+ Object . keys ( response . headers ) . forEach ( k => {
442+ normalisedHeaders [ k . toLowerCase ( ) ] = response . headers [ k ]
443+ } )
444+ if ( normalisedHeaders [ 'www-authenticate' ] ) {
445+ let authHeader = buildDigestHeader ( digestCreds . user , digestCreds . password , response . request . options . method , requestUrl . pathname + requestUrl . search , normalisedHeaders [ 'www-authenticate' ] )
446+ options . headers . Authorization = authHeader ;
447+ }
448+ // response.request.options.merge(options)
449+ sentCreds = true ;
450+ return retry ( options ) ;
438451 }
439- // response.request.options.merge(options)
440- sentCreds = true ;
441- return retry ( options ) ;
452+ return response
453+ } catch ( err ) {
454+ node . warn ( "Digest authentication failed: " + err . message ) ;
455+ return response ;
442456 }
443- return response
444457 } ] ;
445458 } else if ( this . authType === "bearer" ) {
446459 opts . headers . Authorization = `Bearer ${ this . credentials . password || "" } `
@@ -720,13 +733,29 @@ in your Node-RED user directory (${RED.settings.userDir}).
720733
721734 function extractCookies ( setCookie ) {
722735 var cookies = { } ;
736+ if ( ! Array . isArray ( setCookie ) ) {
737+ return cookies ;
738+ }
723739 setCookie . forEach ( function ( c ) {
724- var parsedCookie = cookie . parse ( c ) ;
725- var eq_idx = c . indexOf ( '=' ) ;
726- var key = c . substr ( 0 , eq_idx ) . trim ( )
727- parsedCookie . value = parsedCookie [ key ] ;
728- delete parsedCookie [ key ] ;
729- cookies [ key ] = parsedCookie ;
740+ try {
741+ if ( typeof c !== 'string' ) {
742+ return ;
743+ }
744+ var parsedCookie = cookie . parse ( c ) ;
745+ var eq_idx = c . indexOf ( '=' ) ;
746+ if ( eq_idx === - 1 ) {
747+ return ;
748+ }
749+ var key = c . substr ( 0 , eq_idx ) . trim ( )
750+ if ( ! key ) {
751+ return ;
752+ }
753+ parsedCookie . value = parsedCookie [ key ] ;
754+ delete parsedCookie [ key ] ;
755+ cookies [ key ] = parsedCookie ;
756+ } catch ( err ) {
757+ // Skip malformed cookies
758+ }
730759 } ) ;
731760 return cookies ;
732761 }
@@ -778,6 +807,9 @@ in your Node-RED user directory (${RED.settings.userDir}).
778807 }
779808
780809 function buildDigestHeader ( user , pass , method , path , authHeader ) {
810+ if ( ! authHeader || typeof authHeader !== 'string' ) {
811+ throw new Error ( "Invalid or missing WWW-Authenticate header" ) ;
812+ }
781813 var challenge = { }
782814 var re = / ( [ a - z 0 - 9 _ - ] + ) = (?: " ( [ ^ " ] + ) " | ( [ a - z 0 - 9 _ - ] + ) ) / gi
783815 for ( ; ; ) {
@@ -787,6 +819,12 @@ in your Node-RED user directory (${RED.settings.userDir}).
787819 }
788820 challenge [ match [ 1 ] ] = match [ 2 ] || match [ 3 ]
789821 }
822+ if ( ! challenge . nonce ) {
823+ throw new Error ( "Invalid digest challenge: missing nonce" ) ;
824+ }
825+ if ( ! challenge . realm ) {
826+ throw new Error ( "Invalid digest challenge: missing realm" ) ;
827+ }
790828 var qop = / ( ^ | , ) \s * a u t h \s * ( $ | , ) / . test ( challenge . qop ) && 'auth'
791829 var nc = qop && '00000001'
792830 var cnonce = qop && uuid ( ) . replace ( / - / g, '' )
0 commit comments