Skip to content

Commit

Permalink
chore: pass http agent options to client (#1040)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiwarishubham635 authored Oct 28, 2024
1 parent 3723901 commit 5dd964e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 22 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,27 @@ const client = require('twilio')(accountSid, authToken, {
});
```

### Set HTTP Agent Options

`twilio-node` allows you to set HTTP Agent Options in the Request Client. This feature allows you to re-use your connections. To enable this feature, instantiate the Twilio client with the `keepAlive` flag set to `true`.

Optionally, the socket timeout and maximum number of sockets can also be set. See the example below:

```javascript
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;

const client = require('twilio')(accountSid, authToken, {
timeout: 30000, // HTTPS agent's socket timeout in milliseconds, default is 30000
keepAlive: true, // https.Agent keepAlive option, default is false
keepAliveMsecs: 1000, // https.Agent keepAliveMsecs option in milliseconds, default is 1000
maxSockets: 20, // https.Agent maxSockets option, default is 20
maxTotalSockets: 100, // https.Agent maxTotalSockets option, default is 100
maxFreeSockets: 5, // https.Agent maxFreeSockets option, default is 5
scheduling: "lifo", // https.Agent scheduling option, default is 'lifo'
});
```

### Specify Region and/or Edge

To take advantage of Twilio's [Global Infrastructure](https://www.twilio.com/docs/global-infrastructure), specify the target Region and/or Edge for the client:
Expand Down
20 changes: 8 additions & 12 deletions spec/unit/base/RequestClient.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,17 @@ describe("RequestClient constructor", function () {
30000
);
expect(requestClient.axios.defaults.httpsAgent.options.keepAlive).toBe(
undefined
true
);
expect(requestClient.axios.defaults.httpsAgent.options.keepAliveMsecs).toBe(
undefined
);
expect(requestClient.axios.defaults.httpsAgent.options.maxSockets).toBe(
undefined
);
expect(requestClient.axios.defaults.httpsAgent.options.maxSockets).toBe(20);
expect(
requestClient.axios.defaults.httpsAgent.options.maxTotalSockets
).toBe(undefined);
).toBe(100);
expect(requestClient.axios.defaults.httpsAgent.options.maxFreeSockets).toBe(
undefined
5
);
expect(requestClient.axios.defaults.httpsAgent.options.scheduling).toBe(
undefined
Expand Down Expand Up @@ -156,14 +154,12 @@ describe("RequestClient constructor", function () {
expect(requestClient.axios.defaults.httpsAgent.options.keepAliveMsecs).toBe(
undefined
);
expect(requestClient.axios.defaults.httpsAgent.options.maxSockets).toBe(
undefined
);
expect(requestClient.axios.defaults.httpsAgent.options.maxSockets).toBe(20);
expect(
requestClient.axios.defaults.httpsAgent.options.maxTotalSockets
).toEqual(1500);
expect(requestClient.axios.defaults.httpsAgent.options.maxFreeSockets).toBe(
undefined
5
);
expect(requestClient.axios.defaults.httpsAgent.options.scheduling).toEqual(
"lifo"
Expand Down Expand Up @@ -222,7 +218,7 @@ describe("lastResponse and lastRequest defined", function () {
expect(client.lastRequest.headers).toEqual({
"test-header-key": "test-header-value",
Authorization: "Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk",
Connection: "close",
Connection: "keep-alive",
});
expect(client.lastRequest.data).toEqual({
"test-data-key": "test-data-value",
Expand Down Expand Up @@ -288,7 +284,7 @@ describe("lastRequest defined, lastResponse undefined", function () {
expect(client.lastRequest.headers).toEqual({
"test-header-key": "test-header-value",
Authorization: "Basic dGVzdC11c2VybmFtZTp0ZXN0LXBhc3N3b3Jk",
Connection: "close",
Connection: "keep-alive",
});
expect(client.lastRequest.data).toEqual({
"test-data-key": "test-data-value",
Expand Down
48 changes: 47 additions & 1 deletion src/base/BaseTwilio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,20 @@ namespace Twilio {
logLevel?: string;
userAgentExtensions?: string[];
autoRetry?: boolean;
maxRetryDelay?: number;
maxRetries?: number;

/**
https.Agent options
*/
timeout?: number;
keepAlive?: boolean;
keepAliveMsecs?: number;
maxSockets?: number;
maxTotalSockets?: number;
maxFreeSockets?: number;
scheduling?: "fifo" | "lifo" | undefined;
ca?: string | Buffer;
}

export interface RequestOpts {
Expand Down Expand Up @@ -51,8 +64,22 @@ namespace Twilio {
edge?: string;
region?: string;
logLevel?: string;
autoRetry: boolean;
autoRetry?: boolean;
maxRetryDelay?: number;
maxRetries?: number;

/**
https.Agent options
*/
timeout?: number;
keepAlive?: boolean;
keepAliveMsecs?: number;
maxSockets?: number;
maxTotalSockets?: number;
maxFreeSockets?: number;
scheduling?: "fifo" | "lifo" | undefined;
ca?: string | Buffer;

userAgentExtensions?: string[];
_httpClient?: RequestClient;

Expand Down Expand Up @@ -99,7 +126,17 @@ namespace Twilio {
this.opts.logLevel ??
this.env.TWILIO_LOG_LEVEL ??
process.env.TWILIO_LOG_LEVEL;

this.timeout = this.opts.timeout;
this.keepAlive = this.opts.keepAlive;
this.keepAliveMsecs = this.opts.keepAliveMsecs;
this.maxSockets = this.opts.maxSockets;
this.maxTotalSockets = this.opts.maxTotalSockets;
this.maxFreeSockets = this.opts.maxFreeSockets;
this.scheduling = this.opts.scheduling;
this.ca = this.opts.ca;
this.autoRetry = this.opts.autoRetry || false;
this.maxRetryDelay = this.opts.maxRetryDelay;
this.maxRetries = this.opts.maxRetries;
this.userAgentExtensions = this.opts.userAgentExtensions || [];
this._httpClient = this.opts.httpClient;
Expand All @@ -120,7 +157,16 @@ namespace Twilio {
get httpClient() {
if (!this._httpClient) {
this._httpClient = new RequestClient({
timeout: this.timeout,
keepAlive: this.keepAlive,
keepAliveMsecs: this.keepAliveMsecs,
maxSockets: this.maxSockets,
maxTotalSockets: this.maxTotalSockets,
maxFreeSockets: this.maxFreeSockets,
scheduling: this.scheduling,
ca: this.ca,
autoRetry: this.autoRetry,
maxRetryDelay: this.maxRetryDelay,
maxRetries: this.maxRetries,
});
}
Expand Down
20 changes: 11 additions & 9 deletions src/base/RequestClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const DEFAULT_TIMEOUT = 30000;
const DEFAULT_INITIAL_RETRY_INTERVAL_MILLIS = 100;
const DEFAULT_MAX_RETRY_DELAY = 3000;
const DEFAULT_MAX_RETRIES = 3;
const DEFAULT_MAX_SOCKETS = 20;
const DEFAULT_MAX_FREE_SOCKETS = 5;
const DEFAULT_MAX_TOTAL_SOCKETS = 100;

interface BackoffAxiosRequestConfig extends AxiosRequestConfig {
/**
Expand Down Expand Up @@ -73,6 +76,7 @@ class RequestClient {
autoRetry: boolean;
maxRetryDelay: number;
maxRetries: number;
keepAlive: boolean;

/**
* Make http request
Expand All @@ -94,15 +98,16 @@ class RequestClient {
this.autoRetry = opts.autoRetry || false;
this.maxRetryDelay = opts.maxRetryDelay || DEFAULT_MAX_RETRY_DELAY;
this.maxRetries = opts.maxRetries || DEFAULT_MAX_RETRIES;
this.keepAlive = opts.keepAlive !== false;

// construct an https agent
let agentOpts: https.AgentOptions = {
timeout: this.defaultTimeout,
keepAlive: opts.keepAlive,
keepAlive: this.keepAlive,
keepAliveMsecs: opts.keepAliveMsecs,
maxSockets: opts.maxSockets,
maxTotalSockets: opts.maxTotalSockets,
maxFreeSockets: opts.maxFreeSockets,
maxSockets: opts.maxSockets || DEFAULT_MAX_SOCKETS, // no of sockets open per host
maxTotalSockets: opts.maxTotalSockets || DEFAULT_MAX_TOTAL_SOCKETS, // no of sockets open in total
maxFreeSockets: opts.maxFreeSockets || DEFAULT_MAX_FREE_SOCKETS, // no of free sockets open per host
scheduling: opts.scheduling,
ca: opts.ca,
};
Expand Down Expand Up @@ -165,11 +170,8 @@ class RequestClient {

var headers = opts.headers || {};

if (!headers.Connection && !headers.connection && opts.forever) {
headers.Connection = "keep-alive";
} else if (!headers.Connection && !headers.connection) {
headers.Connection = "close";
}
if (!headers.Connection && !headers.connection)
headers.Connection = this.keepAlive ? "keep-alive" : "close";

let auth = undefined;

Expand Down

0 comments on commit 5dd964e

Please sign in to comment.