|
1 | 1 | import { getEnv } from '@cubejs-backend/shared'; |
2 | 2 | import http from 'http'; |
3 | 3 | import https from 'https'; |
| 4 | +import { HttpsProxyAgent } from 'https-proxy-agent'; |
| 5 | +import { HttpProxyAgent } from 'http-proxy-agent'; |
4 | 6 | import fetch from 'node-fetch'; |
5 | 7 | import crypto from 'crypto'; |
6 | 8 | import WebSocket from 'ws'; |
@@ -50,12 +52,12 @@ class WebSocketTransport implements AgentTransport { |
50 | 52 | clearTimeout(this.pingTimeout); |
51 | 53 | this.onClose(); |
52 | 54 | }); |
53 | | - |
| 55 | + |
54 | 56 | this.wsClient.on('error', e => { |
55 | 57 | connectionPromiseReject(e); |
56 | 58 | this.logger('Agent Error', { error: (e.stack || e).toString() }); |
57 | 59 | }); |
58 | | - |
| 60 | + |
59 | 61 | this.wsClient.on('message', (data: WebSocket.Data) => { |
60 | 62 | try { |
61 | 63 | const { method, params } = JSON.parse(data.toString()); |
@@ -103,17 +105,45 @@ class WebSocketTransport implements AgentTransport { |
103 | 105 | } |
104 | 106 | } |
105 | 107 |
|
| 108 | +function isOnNoProxyList(url: string): boolean { |
| 109 | + const noProxy = process.env.NO_PROXY || process.env.no_proxy; |
| 110 | + if (!noProxy) { |
| 111 | + return false; |
| 112 | + } |
| 113 | + |
| 114 | + const parsedUrl = new URL(url); |
| 115 | + const { hostname } = parsedUrl; |
| 116 | + const noProxyList = noProxy.split(',').map((entry) => entry.trim()); |
| 117 | + |
| 118 | + return noProxyList.some((entry) => { |
| 119 | + if (entry === '*') { |
| 120 | + return true; |
| 121 | + } |
| 122 | + if (entry.startsWith('.')) { |
| 123 | + return hostname.endsWith(entry); |
| 124 | + } |
| 125 | + |
| 126 | + return hostname === entry; |
| 127 | + }); |
| 128 | +} |
| 129 | + |
106 | 130 | class HttpTransport implements AgentTransport { |
107 | | - private agent: http.Agent | https.Agent; |
| 131 | + private agent: http.Agent | https.Agent | HttpProxyAgent<string> | HttpsProxyAgent<string>; |
108 | 132 |
|
109 | 133 | public constructor( |
110 | 134 | private readonly endpointUrl: string |
111 | 135 | ) { |
112 | | - const AgentClass = endpointUrl.startsWith('https') ? https.Agent : http.Agent; |
113 | | - this.agent = new AgentClass({ |
| 136 | + const agentParams = { |
114 | 137 | keepAlive: true, |
115 | 138 | maxSockets: getEnv('agentMaxSockets') |
116 | | - }); |
| 139 | + }; |
| 140 | + if (!isOnNoProxyList(endpointUrl) && (process.env.http_proxy || process.env.https_proxy)) { |
| 141 | + this.agent = endpointUrl.startsWith('https') ? |
| 142 | + new HttpsProxyAgent(process.env.https_proxy, agentParams) : |
| 143 | + new HttpProxyAgent(process.env.http_proxy, agentParams); |
| 144 | + } else { |
| 145 | + this.agent = endpointUrl.startsWith('https') ? new https.Agent(agentParams) : new http.Agent(agentParams); |
| 146 | + } |
117 | 147 | } |
118 | 148 |
|
119 | 149 | public ready() { |
@@ -167,7 +197,7 @@ export default async (event: Record<string, any>, endpointUrl: string, logger: a |
167 | 197 | const sentAt = new Date().toJSON(); |
168 | 198 | const result = await transport.send(toFlush.map(r => ({ ...r, sentAt }))); |
169 | 199 | if (!result && retries > 0) return flush(toFlush, retries - 1); |
170 | | - |
| 200 | + |
171 | 201 | return true; |
172 | 202 | } catch (e: any) { |
173 | 203 | if (retries > 0) return flush(toFlush, retries - 1); |
|
0 commit comments