Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update user agent string for better debugging #680

Merged
merged 4 commits into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
childish-sambino marked this conversation as resolved.
Show resolved Hide resolved
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());
});
});
});