@@ -66,6 +66,7 @@ let debug = require('internal/util/debuglog').debuglog('https', (fn) => {
6666 debug = fn ;
6767} ) ;
6868const net = require ( 'net' ) ;
69+ const { Buffer } = require ( 'buffer' ) ;
6970const { URL , urlToHttpOptions, isURL } = require ( 'internal/url' ) ;
7071const { validateObject } = require ( 'internal/validators' ) ;
7172const { isIP } = require ( 'internal/net' ) ;
@@ -212,16 +213,18 @@ function getTunnelConfigForProxiedHttps(agent, reqOptions) {
212213
213214function establishTunnel ( agent , socket , options , tunnelConfig , afterSocket ) {
214215 const { proxyTunnelPayload } = tunnelConfig ;
216+ const maxHeaderSize = tunnelConfig . requestOptions . maxHeaderSize ||
217+ getOptionValue ( '--max-http-header-size' ) ;
215218 // By default, the socket is in paused mode. Read to look for the 200
216219 // connection established response.
217220 function read ( ) {
218221 let chunk ;
219222 while ( ( chunk = socket . read ( ) ) !== null ) {
220- if ( onProxyData ( chunk ) !== - 1 ) {
221- break ;
223+ if ( onProxyData ( chunk ) ) {
224+ return ;
222225 }
223226 }
224- socket . on ( 'readable' , read ) ;
227+ socket . once ( 'readable' , read ) ;
225228 }
226229
227230 function cleanup ( ) {
@@ -239,14 +242,25 @@ function establishTunnel(agent, socket, options, tunnelConfig, afterSocket) {
239242
240243 // Read the headers from the chunks and check for the status code. If it fails we
241244 // clean up the socket and return an error. Otherwise we establish the tunnel.
242- let buffer = '' ;
245+ let buffer ;
243246 function onProxyData ( chunk ) {
244- const str = chunk . toString ( ) ;
245- debug ( 'onProxyData' , str ) ;
246- buffer += str ;
247+ debug ( 'onProxyData' , chunk . toString ( ) ) ;
248+ buffer = buffer === undefined ? chunk :
249+ Buffer . concat ( [ buffer , chunk ] , buffer . length + chunk . length ) ;
247250 const headerEndIndex = buffer . indexOf ( '\r\n\r\n' ) ;
248- if ( headerEndIndex === - 1 ) return headerEndIndex ;
249- const statusLine = buffer . substring ( 0 , buffer . indexOf ( '\r\n' ) ) ;
251+ const headerLength = headerEndIndex === - 1 ?
252+ buffer . length : headerEndIndex + 4 ;
253+ if ( headerLength > maxHeaderSize ) {
254+ debug ( `Proxy response headers exceed ${ maxHeaderSize } bytes, cleaning up` ) ;
255+ cleanup ( ) ;
256+ const err = new ERR_PROXY_TUNNEL (
257+ `Proxy response headers exceeded ${ maxHeaderSize } bytes` ) ;
258+ afterSocket ( err , socket ) ;
259+ return true ;
260+ }
261+ if ( headerEndIndex === - 1 ) return false ;
262+ const statusLineEndIndex = buffer . indexOf ( '\r\n' ) ;
263+ const statusLine = buffer . subarray ( 0 , statusLineEndIndex ) . toString ( ) ;
250264 const statusCode = statusLine . split ( ' ' ) [ 1 ] ;
251265 if ( statusCode !== '200' ) {
252266 debug ( `onProxyData receives ${ statusCode } , cleaning up` ) ;
@@ -286,7 +300,7 @@ function establishTunnel(agent, socket, options, tunnelConfig, afterSocket) {
286300 } ) ;
287301 tunneldSocket . on ( 'error' , onTLSHandshakeError ) ;
288302 }
289- return headerEndIndex ;
303+ return true ;
290304 }
291305
292306 function onProxyEnd ( ) {
0 commit comments