Skip to content

Commit

Permalink
chore: update user agent string for better debugging (#680)
Browse files Browse the repository at this point in the history
  • Loading branch information
philnash authored Jul 28, 2021
1 parent 76cc8da commit 3f015ce
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 69 deletions.
2 changes: 2 additions & 0 deletions lib/rest/Twilio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ declare namespace Twilio {
* @property lazyLoading - Enable lazy loading, loading time will decrease if enabled
* @property logLevel - Debug logs will be shown. Defaults to none
* @property region - Twilio region to use. Defaults to us1 if edge defined
* @property userAgentExtensions - Additions to the user agent string
*/
export interface TwilioClientOptions {
accountSid?: string;
Expand All @@ -167,6 +168,7 @@ declare namespace Twilio {
lazyLoading?: boolean;
logLevel?: string;
region?: string;
userAgentExtensions?: string[];
}
}

Expand Down
19 changes: 16 additions & 3 deletions lib/rest/Twilio.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
var moduleInfo = require('../../package.json'); /* jshint ignore:line */
var url = require('url'); /* jshint ignore:line */
var util = require('util'); /* jshint ignore:line */
var os = require('os');
var RestException = require('../base/RestException'); /* jshint ignore:line */


Expand Down Expand Up @@ -111,6 +112,7 @@ var RestException = require('../base/RestException'); /* jshint ignore:line */
* @param {boolean} [opts.lazyLoading] -
* Enable lazy loading, loading time will decrease if enabled
* @param {string} [opts.logLevel] - Debug logs will be shown. Defaults to none
* @param {string[]} [opts.userAgentExtensions] - Additions to the user agent string
*
* @returns {Twilio} A new instance of Twilio client
*/
Expand All @@ -129,6 +131,7 @@ function Twilio(username, password, opts) {
this.edge = opts.edge || env.TWILIO_EDGE;
this.region = opts.region || env.TWILIO_REGION;
this.logLevel = opts.logLevel || env.TWILIO_LOG_LEVEL;
this.userAgentExtensions = opts.userAgentExtensions || [];

if (!this.username) {
throw new Error('username is required');
Expand Down Expand Up @@ -246,11 +249,21 @@ Twilio.prototype.request = function request(opts) {
var password = opts.password || this.password;

var headers = opts.headers || {};

var pkgVersion = moduleInfo.version;
var osName = os.platform();
var osArch = os.arch();
var nodeVersion = process.version;
headers['User-Agent'] = util.format(
'twilio-node/%s (node.js %s)',
moduleInfo.version,
process.version
'twilio-node/%s (%s %s) node/%s',
pkgVersion,
osName,
osArch,
nodeVersion
);
this.userAgentExtensions.forEach(extension => {
headers['User-Agent'] += ` ${extension}`;
});
headers['Accept-Charset'] = 'utf-8';

if (opts.method === 'POST' && !headers['Content-Type']) {
Expand Down
5 changes: 4 additions & 1 deletion spec/integration/holodeck.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var util = require('util');
var Request = require('../../lib/http/request');
var RequestClient = require('../../lib/base/RequestClient');
var moduleInfo = require('../../package.json');
var os = require('os');

function Hologram(request, response) {
this.request = request;
Expand All @@ -28,8 +29,10 @@ Holodeck.prototype.addStandardHeaders = function(request) {
'Accept': 'application/json',
'Accept-Charset': 'utf-8',
'User-Agent': util.format(
'twilio-node/%s (node.js %s)',
'twilio-node/%s (%s %s) node/%s',
moduleInfo.version,
os.platform(),
os.arch(),
process.version
)
};
Expand Down
172 changes: 107 additions & 65 deletions spec/unit/rest/Twilio.spec.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,129 @@
'use strict';
const nock = require('nock');
const util = require('util');
var moduleInfo = require('../../../package.json');
var os = require('os');
var url = require('url'); /* jshint ignore:line */

describe('client', () => {
var client;
const twilio = require('../../../lib');

beforeEach(() => {
client = new twilio('ACXXXXXXXX', 'test-password');
});
describe('setting the region', () => {
it('should use the default region if only edge is defined', () => {
const scope = nock('https://api.edge.us1.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
describe('setting region and edge', () => {
beforeEach(() => {
client = new twilio('ACXXXXXXXX', 'test-password');
});
it('should use the provided region if only edge is defined and there is a provided region', () => {
const scope = nock('https://api.edge.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
return client.request({method: 'GET', uri: 'https://api.region.twilio.com'})
.then(() => scope.done());
describe('setting the region', () => {
it('should use no region or edge by default', () => {
const scope = nock('https://api.twilio.com')
.get('/')
.reply(200, 'test response');
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should use the default region if only edge is defined', () => {
const scope = nock('https://api.edge.us1.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should use the provided region if only edge is defined and there is a provided region', () => {
const scope = nock('https://api.edge.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
return client.request({method: 'GET', uri: 'https://api.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region properly if only the region is specified', () => {
const scope = nock('https://api.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly', () => {
const scope = nock('https://api.edge.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly when an edge is already included', () => {
const scope = nock('https://api.edge2.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge2';
return client.request({method: 'GET', uri: 'https://api.edge1.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly when a region is already included', () => {
const scope = nock('https://api.edge.region2.twilio.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.edge.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region properly when a region is already included', () => {
const scope = nock('https://api.region2.twilio.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region properly on a custom domain', () => {
const scope = nock('https://api.region2.domain.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.domain.com'})
.then(() => scope.done());
});
it('should set the region properly when a port is included', () => {
const scope = nock('https://api.region.twilio.com:123')
.get('/')
.reply(200, 'test response');
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com:123'})
.then(() => scope.done());
});
});
it('should set the region properly if only the region is specified', () => {
const scope = nock('https://api.region.twilio.com')
});

describe('adding user agent extensions', () => {
it('sets the user-agent by default', () => {
const client = new twilio('ACXXXXXXXX', 'test-password');
const scope = nock('https://api.twilio.com', {
reqheaders: {
'User-Agent': `twilio-node/${moduleInfo.version} \(${os.platform()} ${os.arch()}\) node\/${process.version}`,
},
})
.get('/')
.reply(200, 'test response');
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly', () => {
const scope = nock('https://api.edge.region.twilio.com')

it('allows for user-agent extensions', () => {
const client = new twilio('ACXXXXXXXX', 'test-password', {
userAgentExtensions: ['twilio-run/2.0.0-test', '@twilio-labs/plugin-serverless/1.1.0-test'],
});
const scope = nock('https://api.twilio.com', {
reqheaders: {
'User-Agent': `twilio-node/${moduleInfo.version} \(${os.platform()} ${os.arch()}\) node\/${process.version} twilio-run\/2.0.0-test @twilio-labs\/plugin-serverless\/1.1.0-test`,
},
})
.get('/')
.reply(200, 'test response');
client.edge = 'edge';
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly when an edge is already included', () => {
const scope = nock('https://api.edge2.region.twilio.com')
.get('/')
.reply(200, 'test response');
client.edge = 'edge2';
return client.request({method: 'GET', uri: 'https://api.edge1.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region and edge properly when a region is already included', () => {
const scope = nock('https://api.edge.region2.twilio.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.edge.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region properly when a region is already included', () => {
const scope = nock('https://api.region2.twilio.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.region.twilio.com'})
.then(() => scope.done());
});
it('should set the region properly on a custom domain', () => {
const scope = nock('https://api.region2.domain.com')
.get('/')
.reply(200, 'test response');
client.region = 'region2';
return client.request({method: 'GET', uri: 'https://api.domain.com'})
.then(() => scope.done());
});
it('should set the region properly when a port is included', () => {
const scope = nock('https://api.region.twilio.com:123')
.get('/')
.reply(200, 'test response');
client.region = 'region';
return client.request({method: 'GET', uri: 'https://api.twilio.com:123'})
.then(() => scope.done());
});
});
});

0 comments on commit 3f015ce

Please sign in to comment.