Skip to content

Commit 58c9111

Browse files
committed
feat: HTTP(S) Proxy support for Node
1 parent 263f209 commit 58c9111

File tree

8 files changed

+60
-5
lines changed

8 files changed

+60
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- [node] HTTP(S) Proxy support
6+
57
## 4.3.4
68

79
- [utils] fix: Broken tslib import - Fixes #1757

packages/node/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@sentry/utils": "4.3.4",
2222
"@types/stack-trace": "0.0.29",
2323
"cookie": "0.3.1",
24+
"https-proxy-agent": "^2.2.1",
2425
"lsmod": "1.0.0",
2526
"stack-trace": "0.0.10",
2627
"tslib": "^1.9.3"

packages/node/src/backend.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { HTTPSTransport, HTTPTransport } from './transports';
1111
* @see NodeClient for more information.
1212
*/
1313
export interface NodeOptions extends Options {
14+
[key: string]: any;
15+
1416
/** Callback that is executed when a fatal global error occurs. */
1517
onFatalError?(error: Error): void;
1618

@@ -19,6 +21,15 @@ export interface NodeOptions extends Options {
1921

2022
/** Maximum time to wait to drain the request queue, before the process is allowed to exit. */
2123
shutdownTimeout?: number;
24+
25+
/** Set a HTTP proxy that should be used for outbound requests. */
26+
httpProxy?: string;
27+
28+
/** Set a HTTPS proxy that should be used for outbound requests. */
29+
httpsProxy?: string;
30+
31+
/** HTTPS proxy certificates path */
32+
caCerts?: string;
2233
}
2334

2435
/** The Sentry Node SDK Backend. */
@@ -101,6 +112,14 @@ export class NodeBackend extends BaseBackend<NodeOptions> {
101112

102113
if (!this.transport) {
103114
const transportOptions = this.options.transportOptions ? this.options.transportOptions : { dsn };
115+
const clientOptions = ['httpProxy', 'httpsProxy', 'caCerts'];
116+
117+
for (const option of clientOptions) {
118+
if (this.options[option]) {
119+
transportOptions[option] = transportOptions[option] || this.options[option];
120+
}
121+
}
122+
104123
this.transport = this.options.transport
105124
? new this.options.transport({ dsn })
106125
: dsn.protocol === 'http'

packages/node/src/declarations.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
11
declare module 'lsmod';
2+
3+
declare module 'https-proxy-agent' {
4+
/** JSDoc */
5+
// tslint:disable-next-line:no-unnecessary-class
6+
export default class HttpsProxyAgent {
7+
public constructor(proxy: string);
8+
}
9+
}

packages/node/src/transports/base.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { API, SentryError } from '@sentry/core';
22
import { SentryEvent, SentryResponse, Status, Transport, TransportOptions } from '@sentry/types';
33
import { serialize } from '@sentry/utils/object';
4+
import * as fs from 'fs';
45
import * as http from 'http';
56
import * as https from 'https';
67
import * as url from 'url';
@@ -33,9 +34,11 @@ export abstract class BaseTransport implements Transport {
3334
...this.api.getRequestHeaders(SDK_NAME, SDK_VERSION),
3435
...this.options.headers,
3536
};
36-
3737
const dsn = this.api.getDsn();
38-
return {
38+
39+
const options: {
40+
[key: string]: any;
41+
} = {
3942
agent: this.client,
4043
headers,
4144
hostname: dsn.host,
@@ -44,6 +47,12 @@ export abstract class BaseTransport implements Transport {
4447
port: dsn.port,
4548
protocol: `${dsn.protocol}:`,
4649
};
50+
51+
if (this.options.caCerts) {
52+
options.ca = fs.readFileSync(this.options.caCerts);
53+
}
54+
55+
return options;
4756
}
4857

4958
/** JSDoc */

packages/node/src/transports/http.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { SentryEvent, SentryResponse, TransportOptions } from '@sentry/types';
22
import * as http from 'http';
3+
import HttpsProxyAgent from 'https-proxy-agent';
34
import { BaseTransport } from './base';
45

5-
/** /** Node http module transport */
6+
/** Node http module transport */
67
export class HTTPTransport extends BaseTransport {
78
/** Create a new instance and set this.agent */
89
public constructor(public options: TransportOptions) {
910
super(options);
10-
this.client = new http.Agent({ keepAlive: true, maxSockets: 100 });
11+
const proxy = options.httpProxy || process.env.http_proxy;
12+
this.client = proxy
13+
? (new HttpsProxyAgent(proxy) as http.Agent)
14+
: new http.Agent({ keepAlive: true, maxSockets: 100 });
1115
}
1216

1317
/**

packages/node/src/transports/https.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { SentryEvent, SentryResponse, TransportOptions } from '@sentry/types';
22
import * as https from 'https';
3+
import HttpsProxyAgent from 'https-proxy-agent';
34
import { BaseTransport } from './base';
45

56
/** Node https module transport */
67
export class HTTPSTransport extends BaseTransport {
78
/** Create a new instance and set this.agent */
89
public constructor(public options: TransportOptions) {
910
super(options);
10-
this.client = new https.Agent({ keepAlive: true, maxSockets: 100 });
11+
const proxy = options.httpsProxy || options.httpProxy || process.env.https_proxy || process.env.http_proxy;
12+
this.client = proxy
13+
? (new HttpsProxyAgent(proxy) as https.Agent)
14+
: new https.Agent({ keepAlive: true, maxSockets: 100 });
1115
}
1216

1317
/**

packages/types/src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,17 @@ export interface SentryResponse {
225225

226226
/** JSDoc */
227227
export interface TransportOptions {
228+
[key: string]: any;
229+
/** Sentry DSN */
228230
dsn: DsnLike;
229231
/** Define custom headers */
230232
headers?: object;
233+
/** Set a HTTP proxy that should be used for outbound requests. */
234+
httpProxy?: string;
235+
/** Set a HTTPS proxy that should be used for outbound requests. */
236+
httpsProxy?: string;
237+
/** HTTPS proxy certificates path */
238+
caCerts?: string;
231239
}
232240

233241
/** JSDoc */

0 commit comments

Comments
 (0)