(agent, reqOptions)
| 158 | // This function computes the tunnel configuration for HTTPS requests. |
| 159 | // The handling of the tunnel connection is done in createConnection. |
| 160 | function getTunnelConfigForProxiedHttps(agent, reqOptions) { |
| 161 | if (!agent[kProxyConfig]) { |
| 162 | return null; |
| 163 | } |
| 164 | if ((reqOptions.protocol || agent.protocol) !== 'https:') { |
| 165 | return null; |
| 166 | } |
| 167 | const shouldUseProxy = checkShouldUseProxy(agent[kProxyConfig], reqOptions); |
| 168 | debug(`getTunnelConfigForProxiedHttps should use proxy for ${reqOptions.host}:${reqOptions.port}:`, shouldUseProxy); |
| 169 | if (!shouldUseProxy) { |
| 170 | return null; |
| 171 | } |
| 172 | const { auth, href } = agent[kProxyConfig]; |
| 173 | // The request is a HTTPS request, assemble the payload for establishing the tunnel. |
| 174 | const ipType = isIP(reqOptions.host); |
| 175 | // The request target must put IPv6 address in square brackets. |
| 176 | // Here reqOptions is already processed by urlToHttpOptions so we'll add them back if necessary. |
| 177 | // See https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2 |
| 178 | const requestHost = ipType === 6 ? `[${reqOptions.host}]` : reqOptions.host; |
| 179 | const requestPort = reqOptions.port || agent.defaultPort; |
| 180 | const endpoint = `${requestHost}:${requestPort}`; |
| 181 | // The ClientRequest constructor should already have validated the host and the port. |
| 182 | // When the request options come from a string invalid characters would be stripped away, |
| 183 | // when it's an object ERR_INVALID_CHAR would be thrown. Here we just assert in case |
| 184 | // agent.createConnection() is called with invalid options. |
| 185 | assert(!endpoint.includes('\r')); |
| 186 | assert(!endpoint.includes('\n')); |
| 187 | |
| 188 | let payload = `CONNECT ${endpoint} HTTP/1.1\r\n`; |
| 189 | // The parseProxyConfigFromEnv() method should have already validated the authorization header |
| 190 | // value. |
| 191 | if (auth) { |
| 192 | payload += `proxy-authorization: ${auth}\r\n`; |
| 193 | } |
| 194 | if (agent.keepAlive || agent.maxSockets !== Infinity) { |
| 195 | payload += 'proxy-connection: keep-alive\r\n'; |
| 196 | } |
| 197 | payload += `host: ${endpoint}`; |
| 198 | payload += '\r\n\r\n'; |
| 199 | |
| 200 | const result = { |
| 201 | __proto__: null, |
| 202 | proxyTunnelPayload: payload, |
| 203 | requestOptions: { // Options used for the request sent after the tunnel is established. |
| 204 | __proto__: null, |
| 205 | servername: reqOptions.servername || ipType ? undefined : reqOptions.host, |
| 206 | ...reqOptions, |
| 207 | }, |
| 208 | }; |
| 209 | debug(`updated request for HTTPS proxy ${href} with`, result); |
| 210 | return result; |
| 211 | }; |
| 212 | |
| 213 | function establishTunnel(agent, socket, options, tunnelConfig, afterSocket) { |
| 214 | const { proxyTunnelPayload } = tunnelConfig; |
no test coverage detected
searching dependent graphs…