MCPcopy Index your code
hub / github.com/nodejs/node / establishTunnel

Function establishTunnel

lib/https.js:213–321  ·  view source on GitHub ↗
(agent, socket, options, tunnelConfig, afterSocket)

Source from the content-addressed store, hash-verified

211};
212
213function establishTunnel(agent, socket, options, tunnelConfig, afterSocket) {
214 const { proxyTunnelPayload } = tunnelConfig;
215 // By default, the socket is in paused mode. Read to look for the 200
216 // connection established response.
217 function read() {
218 let chunk;
219 while ((chunk = socket.read()) !== null) {
220 if (onProxyData(chunk) !== -1) {
221 break;
222 }
223 }
224 socket.on('readable', read);
225 }
226
227 function cleanup() {
228 socket.removeListener('end', onProxyEnd);
229 socket.removeListener('error', onProxyError);
230 socket.removeListener('readable', read);
231 socket.setTimeout(0); // Clear the timeout for the tunnel establishment.
232 }
233
234 function onProxyError(err) {
235 debug('onProxyError', err);
236 cleanup();
237 afterSocket(err, socket);
238 }
239
240 // Read the headers from the chunks and check for the status code. If it fails we
241 // clean up the socket and return an error. Otherwise we establish the tunnel.
242 let buffer = '';
243 function onProxyData(chunk) {
244 const str = chunk.toString();
245 debug('onProxyData', str);
246 buffer += str;
247 const headerEndIndex = buffer.indexOf('\r\n\r\n');
248 if (headerEndIndex === -1) return headerEndIndex;
249 const statusLine = buffer.substring(0, buffer.indexOf('\r\n'));
250 const statusCode = statusLine.split(' ')[1];
251 if (statusCode !== '200') {
252 debug(`onProxyData receives ${statusCode}, cleaning up`);
253 cleanup();
254 const targetHost = proxyTunnelPayload.split('\r')[0].split(' ')[1];
255 const message = `Failed to establish tunnel to ${targetHost} via ${agent[kProxyConfig].href}: ${statusLine}`;
256 const err = new ERR_PROXY_TUNNEL(message);
257 err.statusCode = NumberParseInt(statusCode);
258 afterSocket(err, socket);
259 } else {
260 // https://datatracker.ietf.org/doc/html/rfc9110#CONNECT
261 // RFC 9110 says that it can be 2xx but in the real world, proxy clients generally only
262 // accepts 200.
263 // Proxy servers are not supposed to send anything after the headers - the payload must be
264 // be empty. So after this point we will proceed with the tunnel e.g. starting TLS handshake.
265 debug('onProxyData receives 200, establishing tunnel');
266 cleanup();
267
268 // Reuse the tunneled socket to perform the TLS handshake with the endpoint,
269 // then send the request.
270 const { requestOptions } = tunnelConfig;

Callers 1

onProxyConnectionFunction · 0.85

Calls 5

readFunction · 0.70
debugFunction · 0.50
setTimeoutMethod · 0.45
onMethod · 0.45
writeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…