15
15
*
16
16
*/
17
17
18
- import { URL } from 'url' ;
19
18
import { log } from './logging' ;
20
19
import { LogVerbosity } from './constants' ;
21
20
import { getDefaultAuthority } from './resolver' ;
22
- import { parseTarget } from './resolver-dns' ;
23
21
import { Socket } from 'net' ;
24
22
import * as http from 'http' ;
25
23
import * as tls from 'tls' ;
@@ -30,6 +28,7 @@ import {
30
28
subchannelAddressToString ,
31
29
} from './subchannel' ;
32
30
import { ChannelOptions } from './channel-options' ;
31
+ import { GrpcUri , parseUri , splitHostPort , uriToString } from './uri-parser' ;
33
32
34
33
const TRACER_NAME = 'proxy' ;
35
34
@@ -61,31 +60,30 @@ function getProxyInfo(): ProxyInfo {
61
60
} else {
62
61
return { } ;
63
62
}
64
- let proxyUrl : URL ;
65
- try {
66
- proxyUrl = new URL ( proxyEnv ) ;
67
- } catch ( e ) {
63
+ const proxyUrl = parseUri ( proxyEnv ) ;
64
+ if ( proxyUrl === null ) {
68
65
log ( LogVerbosity . ERROR , `cannot parse value of "${ envVar } " env var` ) ;
69
66
return { } ;
70
67
}
71
- if ( proxyUrl . protocol !== 'http: ' ) {
68
+ if ( proxyUrl . scheme !== 'http' ) {
72
69
log (
73
70
LogVerbosity . ERROR ,
74
- `"${ proxyUrl . protocol } " scheme not supported in proxy URI`
71
+ `"${ proxyUrl . scheme } " scheme not supported in proxy URI`
75
72
) ;
76
73
return { } ;
77
74
}
75
+ const splitPath = proxyUrl . path . split ( '@' ) ;
76
+ let host : string ;
78
77
let userCred : string | null = null ;
79
- if ( proxyUrl . username ) {
80
- if ( proxyUrl . password ) {
81
- log ( LogVerbosity . INFO , 'userinfo found in proxy URI' ) ;
82
- userCred = `${ proxyUrl . username } :${ proxyUrl . password } ` ;
83
- } else {
84
- userCred = proxyUrl . username ;
85
- }
78
+ if ( splitPath . length === 2 ) {
79
+ log ( LogVerbosity . INFO , 'userinfo found in proxy URI' ) ;
80
+ userCred = splitPath [ 0 ] ;
81
+ host = splitPath [ 1 ] ;
82
+ } else {
83
+ host = proxyUrl . path ;
86
84
}
87
85
const result : ProxyInfo = {
88
- address : proxyUrl . host ,
86
+ address : host ,
89
87
} ;
90
88
if ( userCred ) {
91
89
result . creds = userCred ;
@@ -113,12 +111,12 @@ function getNoProxyHostList(): string[] {
113
111
}
114
112
115
113
export interface ProxyMapResult {
116
- target : string ;
114
+ target : GrpcUri ;
117
115
extraOptions : ChannelOptions ;
118
116
}
119
117
120
118
export function mapProxyName (
121
- target : string ,
119
+ target : GrpcUri ,
122
120
options : ChannelOptions
123
121
) : ProxyMapResult {
124
122
const noProxyResult : ProxyMapResult = {
@@ -129,32 +127,32 @@ export function mapProxyName(
129
127
if ( ! proxyInfo . address ) {
130
128
return noProxyResult ;
131
129
}
132
- const parsedTarget = parseTarget ( target ) ;
133
- if ( ! parsedTarget ) {
130
+ const hostPort = splitHostPort ( target . path ) ;
131
+ if ( ! hostPort ) {
134
132
return noProxyResult ;
135
133
}
136
- const serverHost = parsedTarget . host ;
134
+ const serverHost = hostPort . host ;
137
135
for ( const host of getNoProxyHostList ( ) ) {
138
136
if ( host === serverHost ) {
139
137
trace ( 'Not using proxy for target in no_proxy list: ' + target ) ;
140
138
return noProxyResult ;
141
139
}
142
140
}
143
141
const extraOptions : ChannelOptions = {
144
- 'grpc.http_connect_target' : target ,
142
+ 'grpc.http_connect_target' : uriToString ( target ) ,
145
143
} ;
146
144
if ( proxyInfo . creds ) {
147
145
extraOptions [ 'grpc.http_connect_creds' ] = proxyInfo . creds ;
148
146
}
149
147
return {
150
- target : `dns: ${ proxyInfo . address } ` ,
148
+ target : { path : proxyInfo . address } ,
151
149
extraOptions : extraOptions ,
152
150
} ;
153
151
}
154
152
155
153
export interface ProxyConnectionResult {
156
154
socket ?: Socket ;
157
- realTarget ?: string ;
155
+ realTarget ?: GrpcUri ;
158
156
}
159
157
160
158
export function getProxiedConnection (
@@ -166,9 +164,13 @@ export function getProxiedConnection(
166
164
return Promise . resolve < ProxyConnectionResult > ( { } ) ;
167
165
}
168
166
const realTarget = channelOptions [ 'grpc.http_connect_target' ] as string ;
169
- const parsedTarget = parseTarget ( realTarget ) ! ;
167
+ const parsedTarget = parseUri ( realTarget ) ;
168
+ if ( parsedTarget === null ) {
169
+ return Promise . resolve < ProxyConnectionResult > ( { } ) ;
170
+ }
170
171
const options : http . RequestOptions = {
171
172
method : 'CONNECT' ,
173
+ path : parsedTarget . path ,
172
174
} ;
173
175
// Connect to the subchannel address as a proxy
174
176
if ( isTcpSubchannelAddress ( address ) ) {
@@ -177,11 +179,6 @@ export function getProxiedConnection(
177
179
} else {
178
180
options . socketPath = address . path ;
179
181
}
180
- if ( parsedTarget . port === undefined ) {
181
- options . path = parsedTarget . host ;
182
- } else {
183
- options . path = `${ parsedTarget . host } :${ parsedTarget . port } ` ;
184
- }
185
182
if ( 'grpc.http_connect_creds' in channelOptions ) {
186
183
options . headers = {
187
184
'Proxy-Authorization' :
@@ -205,23 +202,27 @@ export function getProxiedConnection(
205
202
' through proxy ' +
206
203
proxyAddressString
207
204
) ;
205
+ resolve ( {
206
+ socket,
207
+ realTarget : parsedTarget ,
208
+ } ) ;
208
209
if ( 'secureContext' in connectionOptions ) {
209
210
/* The proxy is connecting to a TLS server, so upgrade this socket
210
211
* connection to a TLS connection.
211
212
* This is a workaround for https://github.com/nodejs/node/issues/32922
212
213
* See https://github.com/grpc/grpc-node/pull/1369 for more info. */
213
214
const cts = tls . connect ( {
214
215
...connectionOptions ,
215
- host : getDefaultAuthority ( realTarget ) ,
216
+ host : getDefaultAuthority ( parsedTarget ) ,
216
217
socket : socket ,
217
218
} , ( ) => {
218
- resolve ( { socket : cts , realTarget } ) ;
219
+ resolve ( { socket : cts , realTarget : parsedTarget } ) ;
219
220
}
220
221
) ;
221
222
} else {
222
223
resolve ( {
223
224
socket,
224
- realTarget,
225
+ realTarget : parsedTarget ,
225
226
} ) ;
226
227
}
227
228
} else {
0 commit comments