@@ -19,28 +19,35 @@ function isSecureEndpoint(): boolean {
19
19
20
20
interface HttpConnectOpts extends net . TcpNetConnectOpts {
21
21
secureEndpoint : false ;
22
+ protocol ?: string ;
22
23
}
23
24
24
25
interface HttpsConnectOpts extends tls . ConnectionOptions {
25
- port : number ;
26
26
secureEndpoint : true ;
27
+ protocol ?: string ;
28
+ port : number ;
27
29
}
28
30
29
31
export type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts ;
30
32
33
+ const INTERNAL = Symbol ( 'AgentBaseInternalState' ) ;
34
+
35
+ interface InternalState {
36
+ defaultPort ?: number ;
37
+ protocol ?: string ;
38
+ currentSocket ?: Duplex ;
39
+ }
40
+
31
41
export abstract class Agent extends http . Agent {
32
- _defaultPort ?: number ;
33
- _protocol ?: string ;
34
- _currentSocket ?: Duplex ;
42
+ private [ INTERNAL ] : InternalState ;
35
43
36
44
// Set by `http.Agent` - missing from `@types/node`
37
45
options ! : Partial < net . TcpNetConnectOpts & tls . ConnectionOptions > ;
38
46
keepAlive ! : boolean ;
39
47
40
48
constructor ( opts ?: http . AgentOptions ) {
41
49
super ( opts ) ;
42
- this . _defaultPort = undefined ;
43
- this . _protocol = undefined ;
50
+ this [ INTERNAL ] = { } ;
44
51
}
45
52
46
53
abstract connect (
@@ -53,51 +60,79 @@ export abstract class Agent extends http.Agent {
53
60
options : AgentConnectOpts ,
54
61
cb : ( err : Error | null , s ?: Duplex ) => void
55
62
) {
56
- const o = {
57
- ...options ,
58
- secureEndpoint : options . secureEndpoint ?? isSecureEndpoint ( ) ,
59
- } ;
63
+ // Need to determine whether this is an `http` or `https` request.
64
+ // First check the `secureEndpoint` property explicitly, since this
65
+ // means that a parent `Agent` is "passing through" to this instance.
66
+ let secureEndpoint =
67
+ typeof options . secureEndpoint === 'boolean'
68
+ ? options . secureEndpoint
69
+ : undefined ;
70
+
71
+ // If no explicit `secure` endpoint, check if `protocol` property is
72
+ // set. This will usually be the case since using a full string URL
73
+ // or `URL` instance should be the most common case.
74
+ if (
75
+ typeof secureEndpoint === 'undefined' &&
76
+ typeof options . protocol === 'string'
77
+ ) {
78
+ secureEndpoint = options . protocol === 'https:' ;
79
+ }
80
+
81
+ // Finally, if no `protocol` property was set, then fall back to
82
+ // checking the stack trace of the current call stack, and try to
83
+ // detect the "https" module.
84
+ if ( typeof secureEndpoint === 'undefined' ) {
85
+ secureEndpoint = isSecureEndpoint ( ) ;
86
+ }
87
+
88
+ const connectOpts = { ...options , secureEndpoint } ;
60
89
Promise . resolve ( )
61
- . then ( ( ) => this . connect ( req , o ) )
90
+ . then ( ( ) => this . connect ( req , connectOpts ) )
62
91
. then ( ( socket ) => {
63
92
if ( socket instanceof http . Agent ) {
64
93
// @ts -expect-error `addRequest()` isn't defined in `@types/node`
65
- return socket . addRequest ( req , o ) ;
94
+ return socket . addRequest ( req , connectOpts ) ;
66
95
}
67
- this . _currentSocket = socket ;
96
+ this [ INTERNAL ] . currentSocket = socket ;
68
97
// @ts -expect-error `createSocket()` isn't defined in `@types/node`
69
98
super . createSocket ( req , options , cb ) ;
70
99
} , cb ) ;
71
100
}
72
101
73
102
createConnection ( ) : Duplex {
74
- if ( ! this . _currentSocket ) {
75
- throw new Error ( 'no socket' ) ;
103
+ const socket = this [ INTERNAL ] . currentSocket ;
104
+ this [ INTERNAL ] . currentSocket = undefined ;
105
+ if ( ! socket ) {
106
+ throw new Error (
107
+ 'No socket was returned in the `connect()` function'
108
+ ) ;
76
109
}
77
- return this . _currentSocket ;
110
+ return socket ;
78
111
}
79
112
80
113
get defaultPort ( ) : number {
81
- if ( typeof this . _defaultPort === 'number' ) {
82
- return this . _defaultPort ;
83
- }
84
- const port = this . protocol === 'https:' ? 443 : 80 ;
85
- return port ;
114
+ return (
115
+ this [ INTERNAL ] . defaultPort ??
116
+ ( this . protocol === 'https:' ? 443 : 80 )
117
+ ) ;
86
118
}
87
119
88
120
set defaultPort ( v : number ) {
89
- this . _defaultPort = v ;
121
+ if ( this [ INTERNAL ] ) {
122
+ this [ INTERNAL ] . defaultPort = v ;
123
+ }
90
124
}
91
125
92
126
get protocol ( ) : string {
93
- if ( typeof this . _protocol === 'string' ) {
94
- return this . _protocol ;
95
- }
96
- const p = isSecureEndpoint ( ) ? 'https:' : 'http:' ;
97
- return p ;
127
+ return (
128
+ this [ INTERNAL ] . protocol ??
129
+ ( isSecureEndpoint ( ) ? 'https:' : 'http:' )
130
+ ) ;
98
131
}
99
132
100
133
set protocol ( v : string ) {
101
- this . _protocol = v ;
134
+ if ( this [ INTERNAL ] ) {
135
+ this [ INTERNAL ] . protocol = v ;
136
+ }
102
137
}
103
138
}
0 commit comments