@@ -86,7 +86,7 @@ import {
86
86
getDnsLookupFunction ,
87
87
getTrustedCAs ,
88
88
buildUpstreamErrorTags ,
89
- getUrlHostname ,
89
+ getEffectiveHostname ,
90
90
applyDestinationTransforms
91
91
} from '../passthrough-handling' ;
92
92
@@ -422,11 +422,17 @@ export class PassThroughStepImpl extends PassThroughStep {
422
422
// Capture raw request data:
423
423
let { method, url : reqUrl , rawHeaders, destination } = clientReq as OngoingRequest ;
424
424
let { protocol, pathname, search : query } = url . parse ( reqUrl ) ;
425
- let hostname : string = destination . hostname ;
425
+ const clientSocket = ( clientReq as any ) . socket as net . Socket ;
426
+
427
+ // Actual IP address or hostname
428
+ let hostAddress = destination . hostname ;
429
+ // Same as hostAddress, unless it's an IP, in which case it's our best guess of the
430
+ // functional 'name' for the host (from Host header or SNI).
431
+ let hostname : string = getEffectiveHostname ( hostAddress , clientSocket , rawHeaders ) ;
426
432
let port : string | null | undefined = destination . port . toString ( ) ;
427
433
428
434
// Check if this request is a request loop:
429
- if ( isSocketLoop ( this . outgoingSockets , ( clientReq as any ) . socket ) ) {
435
+ if ( isSocketLoop ( this . outgoingSockets , clientSocket ) ) {
430
436
throw new Error ( oneLine `
431
437
Passthrough loop detected. This probably means you're sending a request directly
432
438
to a passthrough endpoint, which is forwarding it to the target URL, which is a
@@ -444,8 +450,8 @@ export class PassThroughStepImpl extends PassThroughStep {
444
450
445
451
const isH2Downstream = isHttp2 ( clientReq ) ;
446
452
447
- hostname = await getClientRelativeHostname (
448
- hostname ,
453
+ hostAddress = await getClientRelativeHostname (
454
+ hostAddress ,
449
455
clientReq . remoteIpAddress ,
450
456
getDnsLookupFunction ( this . lookupOptions )
451
457
) ;
@@ -466,6 +472,8 @@ export class PassThroughStepImpl extends PassThroughStep {
466
472
matchReplaceBody
467
473
} = this . transformRequest ;
468
474
475
+ const originalHostname = hostname ;
476
+
469
477
( {
470
478
reqUrl,
471
479
protocol,
@@ -484,6 +492,12 @@ export class PassThroughStepImpl extends PassThroughStep {
484
492
query
485
493
} ) ) ;
486
494
495
+ // If you modify the hostname, we also treat that as modifying the
496
+ // resulting destination in turn:
497
+ if ( hostname !== originalHostname ) {
498
+ hostAddress = hostname ;
499
+ }
500
+
487
501
if ( replaceMethod ) {
488
502
method = replaceMethod ;
489
503
}
@@ -579,8 +593,7 @@ export class PassThroughStepImpl extends PassThroughStep {
579
593
580
594
if ( modifiedReq ?. response ) {
581
595
if ( modifiedReq . response === 'close' ) {
582
- const socket : net . Socket = ( clientReq as any ) . socket ;
583
- socket . end ( ) ;
596
+ clientSocket . end ( ) ;
584
597
throw new AbortError ( 'Connection closed intentionally by rule' , 'E_RULE_BREQ_CLOSE' ) ;
585
598
} else if ( modifiedReq . response === 'reset' ) {
586
599
requireSocketResetSupport ( ) ;
@@ -594,18 +607,27 @@ export class PassThroughStepImpl extends PassThroughStep {
594
607
}
595
608
596
609
method = modifiedReq ?. method || method ;
597
- reqUrl = modifiedReq ?. url || reqUrl ;
610
+
611
+ // Reparse the new URL, if necessary
612
+ if ( modifiedReq ?. url ) {
613
+ if ( ! isAbsoluteUrl ( modifiedReq ?. url ) ) throw new Error ( "Overridden request URLs must be absolute" ) ;
614
+
615
+ reqUrl = modifiedReq . url ;
616
+
617
+ const parsedUrl = url . parse ( reqUrl ) ;
618
+ ( { protocol, port, pathname, search : query } = parsedUrl ) ;
619
+ hostname = parsedUrl . hostname ! ;
620
+ hostAddress = hostname ;
621
+ }
598
622
599
623
let headers = modifiedReq ?. headers || clientHeaders ;
600
624
601
625
// We need to make sure the Host/:authority header is updated correctly - following the user's returned value if
602
626
// they provided one, but updating it if not to match the effective target URL of the request:
603
- const expectedTargetUrl = modifiedReq ?. url ?? reqUrl ;
604
-
605
627
Object . assign ( headers ,
606
628
isH2Downstream
607
- ? getH2HeadersAfterModification ( expectedTargetUrl , clientHeaders , modifiedReq ?. headers )
608
- : { 'host' : getHostAfterModification ( expectedTargetUrl , clientHeaders , modifiedReq ?. headers ) }
629
+ ? getH2HeadersAfterModification ( reqUrl , clientHeaders , modifiedReq ?. headers )
630
+ : { 'host' : getHostAfterModification ( reqUrl , clientHeaders , modifiedReq ?. headers ) }
609
631
) ;
610
632
611
633
validateCustomHeaders (
@@ -630,14 +652,6 @@ export class PassThroughStepImpl extends PassThroughStep {
630
652
}
631
653
}
632
654
633
- // Reparse the new URL, if necessary
634
- if ( modifiedReq ?. url ) {
635
- if ( ! isAbsoluteUrl ( modifiedReq ?. url ) ) throw new Error ( "Overridden request URLs must be absolute" ) ;
636
- const parsedUrl = url . parse ( reqUrl ) ;
637
- ( { protocol, port, pathname, search : query } = parsedUrl ) ;
638
- hostname = parsedUrl . hostname ! ;
639
- }
640
-
641
655
rawHeaders = objectHeadersToRaw ( headers ) ;
642
656
}
643
657
@@ -726,7 +740,7 @@ export class PassThroughStepImpl extends PassThroughStep {
726
740
serverReq = await makeRequest ( {
727
741
protocol,
728
742
method,
729
- hostname,
743
+ hostname : hostAddress ,
730
744
port,
731
745
family,
732
746
path : `${ pathname || '/' } ${ query || '' } ` ,
@@ -739,7 +753,7 @@ export class PassThroughStepImpl extends PassThroughStep {
739
753
agent,
740
754
741
755
// TLS options:
742
- ...getUpstreamTlsOptions ( strictHttpsChecks ) ,
756
+ ...getUpstreamTlsOptions ( { strictHttpsChecks, serverName : hostname } ) ,
743
757
...clientCert ,
744
758
...caConfig
745
759
} , ( serverRes ) => ( async ( ) => {
@@ -944,7 +958,7 @@ export class PassThroughStepImpl extends PassThroughStep {
944
958
}
945
959
946
960
if ( modifiedRes === 'close' ) {
947
- ( clientReq as any ) . socket . end ( ) ;
961
+ clientSocket . end ( ) ;
948
962
} else if ( modifiedRes === 'reset' ) {
949
963
requireSocketResetSupport ( ) ;
950
964
resetOrDestroy ( clientReq ) ;
@@ -1151,12 +1165,10 @@ export class PassThroughStepImpl extends PassThroughStep {
1151
1165
// Fire rule events, to allow in-depth debugging of upstream traffic & modifications,
1152
1166
// so anybody interested can see _exactly_ what we're sending upstream here:
1153
1167
if ( options . emitEventCallback ) {
1154
- const urlHost = getUrlHostname ( hostname , rawHeaders ) ;
1155
-
1156
1168
options . emitEventCallback ( 'passthrough-request-head' , {
1157
1169
method,
1158
1170
protocol : protocol ! . replace ( / : $ / , '' ) ,
1159
- hostname : urlHost ,
1171
+ hostname,
1160
1172
port,
1161
1173
path : `${ pathname || '/' } ${ query || '' } ` ,
1162
1174
rawHeaders
0 commit comments