@@ -415,6 +415,19 @@ export class PassThroughHandler extends PassThroughHandlerDefinition {
415415 let { method, url : reqUrl , rawHeaders } = clientReq as OngoingRequest ;
416416 let { protocol, hostname, port, path } = url . parse ( reqUrl ) ;
417417
418+ // Check if this request is a request loop:
419+ if ( isSocketLoop ( this . outgoingSockets , ( < any > clientReq ) . socket ) ) {
420+ throw new Error ( oneLine `
421+ Passthrough loop detected. This probably means you're sending a request directly
422+ to a passthrough endpoint, which is forwarding it to the target URL, which is a
423+ passthrough endpoint, which is forwarding it to the target URL, which is a
424+ passthrough endpoint...` +
425+ '\n\n' + oneLine `
426+ You should either explicitly mock a response for this URL (${ reqUrl } ), or use
427+ the server as a proxy, instead of making requests to it directly.
428+ ` ) ;
429+ }
430+
418431 // We have to capture the request stream immediately, to make sure nothing is lost if it
419432 // goes past its max length (truncating the data) before we start sending upstream.
420433 const clientReqBody = clientReq . body . asStream ( ) ;
@@ -456,19 +469,8 @@ export class PassThroughHandler extends PassThroughHandlerDefinition {
456469 // If it's an explicit custom value, use that directly.
457470 hostHeader [ 1 ] = updateHostHeader ;
458471 } // Otherwise: falsey means don't touch it.
459- }
460472
461- // Check if this request is a request loop:
462- if ( isSocketLoop ( this . outgoingSockets , ( < any > clientReq ) . socket ) ) {
463- throw new Error ( oneLine `
464- Passthrough loop detected. This probably means you're sending a request directly
465- to a passthrough endpoint, which is forwarding it to the target URL, which is a
466- passthrough endpoint, which is forwarding it to the target URL, which is a
467- passthrough endpoint...` +
468- '\n\n' + oneLine `
469- You should either explicitly mock a response for this URL (${ reqUrl } ), or use
470- the server as a proxy, instead of making requests to it directly.
471- ` ) ;
473+ reqUrl = new URL ( `${ protocol } //${ hostname } ${ ( port ? `:${ port } ` : '' ) } /${ path } ` ) . toString ( ) ;
472474 }
473475
474476 // Override the request details, if a transform or callback is specified:
@@ -571,10 +573,14 @@ export class PassThroughHandler extends PassThroughHandlerDefinition {
571573 }
572574 } else if ( this . beforeRequest ) {
573575 const completedRequest = await waitForCompletedRequest ( clientReq ) ;
576+ const clientRawHeaders = completedRequest . rawHeaders ;
577+ const clientHeaders = rawHeadersToObject ( clientRawHeaders ) ;
578+
574579 const modifiedReq = await this . beforeRequest ( {
575580 ...completedRequest ,
576- headers : _ . cloneDeep ( rawHeadersToObject ( completedRequest . rawHeaders ) ) ,
577- rawHeaders : _ . cloneDeep ( completedRequest . rawHeaders )
581+ url : reqUrl , // May have been overwritten by forwarding
582+ headers : _ . cloneDeep ( clientHeaders ) ,
583+ rawHeaders : _ . cloneDeep ( clientRawHeaders )
578584 } ) ;
579585
580586 if ( modifiedReq ?. response ) {
@@ -597,15 +603,24 @@ export class PassThroughHandler extends PassThroughHandlerDefinition {
597603 reqUrl = modifiedReq ?. url || reqUrl ;
598604
599605 headersManuallyModified = ! ! modifiedReq ?. headers ;
600- const clientHeaders = rawHeadersToObject ( clientReq . rawHeaders )
601606 let headers = modifiedReq ?. headers || clientHeaders ;
602- if ( ! this . forwarding || this . forwarding . updateHostHeader === false ) {
603- Object . assign ( headers ,
604- isH2Downstream
605- ? getH2HeadersAfterModification ( reqUrl , clientHeaders , modifiedReq ?. headers )
606- : { 'host' : getHostAfterModification ( reqUrl , clientHeaders , modifiedReq ?. headers ) }
607+
608+ // We need to make sure the Host/:authority header is updated correctly - following the user's returned value if
609+ // they provided one, but updating it if not to match the effective target URL of the request:
610+ const expectedTargetUrl = modifiedReq ?. url
611+ ?? (
612+ // If not overridden, we fall back to the original value, but we need to handle changes that forwarding
613+ // might have made as well, especially if it's intentionally left URL & headers out of sync:
614+ this . forwarding ?. updateHostHeader === false
615+ ? clientReq . url
616+ : reqUrl
607617 ) ;
608- }
618+
619+ Object . assign ( headers ,
620+ isH2Downstream
621+ ? getH2HeadersAfterModification ( expectedTargetUrl , clientHeaders , modifiedReq ?. headers )
622+ : { 'host' : getHostAfterModification ( expectedTargetUrl , clientHeaders , modifiedReq ?. headers ) }
623+ ) ;
609624
610625 validateCustomHeaders (
611626 clientHeaders ,
0 commit comments