| 76 | } |
| 77 | |
| 78 | function ondata(b: Buffer) { |
| 79 | buffers.push(b); |
| 80 | buffersLength += b.length; |
| 81 | |
| 82 | const buffered = Buffer.concat(buffers, buffersLength); |
| 83 | const endOfHeaders = buffered.indexOf('\r\n\r\n'); |
| 84 | |
| 85 | if (endOfHeaders === -1) { |
| 86 | // keep buffering |
| 87 | debugLog('have not received end of HTTP headers yet...'); |
| 88 | read(); |
| 89 | return; |
| 90 | } |
| 91 | |
| 92 | const headerParts = buffered.subarray(0, endOfHeaders).toString('ascii').split('\r\n'); |
| 93 | const firstLine = headerParts.shift(); |
| 94 | if (!firstLine) { |
| 95 | socket.destroy(); |
| 96 | return reject(new Error('No header received from proxy CONNECT response')); |
| 97 | } |
| 98 | const firstLineParts = firstLine.split(' '); |
| 99 | const statusCode = +(firstLineParts[1] || 0); |
| 100 | const statusText = firstLineParts.slice(2).join(' '); |
| 101 | const headers: IncomingHttpHeaders = {}; |
| 102 | for (const header of headerParts) { |
| 103 | if (!header) continue; |
| 104 | const firstColon = header.indexOf(':'); |
| 105 | if (firstColon === -1) { |
| 106 | socket.destroy(); |
| 107 | return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`)); |
| 108 | } |
| 109 | const key = header.slice(0, firstColon).toLowerCase(); |
| 110 | const value = header.slice(firstColon + 1).trimStart(); |
| 111 | const current = headers[key]; |
| 112 | if (typeof current === 'string') { |
| 113 | headers[key] = [current, value]; |
| 114 | } else if (Array.isArray(current)) { |
| 115 | current.push(value); |
| 116 | } else { |
| 117 | headers[key] = value; |
| 118 | } |
| 119 | } |
| 120 | debugLog('got proxy server response: %o %o', firstLine, headers); |
| 121 | cleanup(); |
| 122 | resolve({ |
| 123 | connect: { |
| 124 | statusCode, |
| 125 | statusText, |
| 126 | headers, |
| 127 | }, |
| 128 | buffered, |
| 129 | }); |
| 130 | } |
| 131 | |
| 132 | socket.on('error', onerror); |
| 133 | socket.on('end', onend); |