1"use strict"; 2var __importDefault = (this && this.__importDefault) || function (mod) { 3 return (mod && mod.__esModule) ? mod : { "default": mod }; 4}; 5Object.defineProperty(exports, "__esModule", { value: true }); 6exports.parseProxyResponse = void 0; 7const debug_1 = __importDefault(require("debug")); 8const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response'); 9function parseProxyResponse(socket) { 10 return new Promise((resolve, reject) => { 11 // we need to buffer any HTTP traffic that happens with the proxy before we get 12 // the CONNECT response, so that if the response is anything other than an "200" 13 // response code, then we can re-play the "data" events on the socket once the 14 // HTTP parser is hooked up... 15 let buffersLength = 0; 16 const buffers = []; 17 function read() { 18 const b = socket.read(); 19 if (b) 20 ondata(b); 21 else 22 socket.once('readable', read); 23 } 24 function cleanup() { 25 socket.removeListener('end', onend); 26 socket.removeListener('error', onerror); 27 socket.removeListener('readable', read); 28 } 29 function onend() { 30 cleanup(); 31 debug('onend'); 32 reject(new Error('Proxy connection ended before receiving CONNECT response')); 33 } 34 function onerror(err) { 35 cleanup(); 36 debug('onerror %o', err); 37 reject(err); 38 } 39 function ondata(b) { 40 buffers.push(b); 41 buffersLength += b.length; 42 const buffered = Buffer.concat(buffers, buffersLength); 43 const endOfHeaders = buffered.indexOf('\r\n\r\n'); 44 if (endOfHeaders === -1) { 45 // keep buffering 46 debug('have not received end of HTTP headers yet...'); 47 read(); 48 return; 49 } 50 const headerParts = buffered 51 .slice(0, endOfHeaders) 52 .toString('ascii') 53 .split('\r\n'); 54 const firstLine = headerParts.shift(); 55 if (!firstLine) { 56 socket.destroy(); 57 return reject(new Error('No header received from proxy CONNECT response')); 58 } 59 const firstLineParts = firstLine.split(' '); 60 const statusCode = +firstLineParts[1]; 61 const statusText = firstLineParts.slice(2).join(' '); 62 const headers = {}; 63 for (const header of headerParts) { 64 if (!header) 65 continue; 66 const firstColon = header.indexOf(':'); 67 if (firstColon === -1) { 68 socket.destroy(); 69 return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`)); 70 } 71 const key = header.slice(0, firstColon).toLowerCase(); 72 const value = header.slice(firstColon + 1).trimStart(); 73 const current = headers[key]; 74 if (typeof current === 'string') { 75 headers[key] = [current, value]; 76 } 77 else if (Array.isArray(current)) { 78 current.push(value); 79 } 80 else { 81 headers[key] = value; 82 } 83 } 84 debug('got proxy server response: %o %o', firstLine, headers); 85 cleanup(); 86 resolve({ 87 connect: { 88 statusCode, 89 statusText, 90 headers, 91 }, 92 buffered, 93 }); 94 } 95 socket.on('error', onerror); 96 socket.on('end', onend); 97 read(); 98 }); 99} 100exports.parseProxyResponse = parseProxyResponse; 101//# sourceMappingURL=parse-proxy-response.js.map