@@ -3,6 +3,7 @@ import * as tls from 'tls';
3
3
import * as http from 'http' ;
4
4
import createDebug from 'debug' ;
5
5
import { once } from 'events' ;
6
+ import type { OutgoingHttpHeaders } from 'http' ;
6
7
import { Agent , AgentConnectOpts } from 'agent-base' ;
7
8
8
9
const debug = createDebug ( 'http-proxy-agent' ) ;
@@ -21,7 +22,10 @@ type ConnectOpts<T> = {
21
22
: never ;
22
23
} [ keyof ConnectOptsMap ] ;
23
24
24
- export type HttpProxyAgentOptions < T > = ConnectOpts < T > & http . AgentOptions ;
25
+ export type HttpProxyAgentOptions < T > = ConnectOpts < T > &
26
+ http . AgentOptions & {
27
+ headers ?: OutgoingHttpHeaders | ( ( ) => OutgoingHttpHeaders ) ;
28
+ } ;
25
29
26
30
interface HttpProxyAgentClientRequest extends http . ClientRequest {
27
31
outputData ?: {
@@ -43,6 +47,7 @@ export class HttpProxyAgent<Uri extends string> extends Agent {
43
47
static protocols = [ 'http' , 'https' ] as const ;
44
48
45
49
readonly proxy : URL ;
50
+ proxyHeaders : OutgoingHttpHeaders | ( ( ) => OutgoingHttpHeaders ) ;
46
51
connectOpts : net . TcpNetConnectOpts & tls . ConnectionOptions ;
47
52
48
53
get secureProxy ( ) {
@@ -52,6 +57,7 @@ export class HttpProxyAgent<Uri extends string> extends Agent {
52
57
constructor ( proxy : Uri | URL , opts ?: HttpProxyAgentOptions < Uri > ) {
53
58
super ( opts ) ;
54
59
this . proxy = typeof proxy === 'string' ? new URL ( proxy ) : proxy ;
60
+ this . proxyHeaders = opts ?. headers ?? { } ;
55
61
debug ( 'Creating new HttpProxyAgent instance: %o' , this . proxy . href ) ;
56
62
57
63
// Trim off the brackets from IPv6 addresses
@@ -65,7 +71,7 @@ export class HttpProxyAgent<Uri extends string> extends Agent {
65
71
? 443
66
72
: 80 ;
67
73
this . connectOpts = {
68
- ...opts ,
74
+ ...( opts ? omit ( opts , 'headers' ) : null ) ,
69
75
host,
70
76
port,
71
77
} ;
@@ -91,21 +97,29 @@ export class HttpProxyAgent<Uri extends string> extends Agent {
91
97
92
98
// Inject the `Proxy-Authorization` header if necessary.
93
99
req . _header = null ;
100
+ const headers : OutgoingHttpHeaders =
101
+ typeof this . proxyHeaders === 'function'
102
+ ? this . proxyHeaders ( )
103
+ : { ...this . proxyHeaders } ;
94
104
if ( proxy . username || proxy . password ) {
95
105
const auth = `${ decodeURIComponent (
96
106
proxy . username
97
107
) } :${ decodeURIComponent ( proxy . password ) } `;
98
- req . setHeader (
99
- 'Proxy-Authorization' ,
100
- `Basic ${ Buffer . from ( auth ) . toString ( 'base64' ) } `
101
- ) ;
108
+ headers [ 'Proxy-Authorization' ] = `Basic ${ Buffer . from (
109
+ auth
110
+ ) . toString ( 'base64' ) } `;
102
111
}
103
112
104
- if ( ! req . hasHeader ( 'proxy-connection' ) ) {
105
- req . setHeader (
106
- 'Proxy-Connection' ,
107
- this . keepAlive ? 'Keep-Alive' : 'close'
108
- ) ;
113
+ if ( ! headers [ 'Proxy-Connection' ] ) {
114
+ headers [ 'Proxy-Connection' ] = this . keepAlive
115
+ ? 'Keep-Alive'
116
+ : 'close' ;
117
+ }
118
+ for ( const name of Object . keys ( headers ) ) {
119
+ const value = headers [ name ] ;
120
+ if ( value ) {
121
+ req . setHeader ( name , value ) ;
122
+ }
109
123
}
110
124
111
125
// Create a socket connection to the proxy server.
@@ -146,3 +160,21 @@ export class HttpProxyAgent<Uri extends string> extends Agent {
146
160
return socket ;
147
161
}
148
162
}
163
+
164
+ function omit < T extends object , K extends [ ...( keyof T ) [ ] ] > (
165
+ obj : T ,
166
+ ...keys : K
167
+ ) : {
168
+ [ K2 in Exclude < keyof T , K [ number ] > ] : T [ K2 ] ;
169
+ } {
170
+ const ret = { } as {
171
+ [ K in keyof typeof obj ] : ( typeof obj ) [ K ] ;
172
+ } ;
173
+ let key : keyof typeof obj ;
174
+ for ( key in obj ) {
175
+ if ( ! keys . includes ( key ) ) {
176
+ ret [ key ] = obj [ key ] ;
177
+ }
178
+ }
179
+ return ret ;
180
+ }
0 commit comments