From 7fd79a41c3f638700f297b1383b684a1c4f99ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20H=C3=B6rl?= Date: Sun, 5 Jan 2014 18:08:58 +0100 Subject: [PATCH 1/3] Add support for (fallback_)application_name --- lib/client.js | 27 ++++--- lib/connection-parameters.js | 26 ++++++- lib/connection.js | 19 ++--- lib/defaults.js | 5 +- test/integration/client/appname-tests.js | 89 ++++++++++++++++++++++++ 5 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 test/integration/client/appname-tests.js diff --git a/lib/client.js b/lib/client.js index dc8edc746..490e1d183 100644 --- a/lib/client.js +++ b/lib/client.js @@ -52,18 +52,12 @@ Client.prototype.connect = function(callback) { if(self.ssl) { con.requestSsl(); } else { - con.startup({ - user: self.user, - database: self.database - }); + con.startup(self.getStartupConf()); } }); con.on('sslconnect', function() { - con.startup({ - user: self.user, - database: self.database - }); + con.startup(self.getStartupConf()); }); function checkPgPass(cb) { @@ -194,6 +188,23 @@ Client.prototype.connect = function(callback) { }; +Client.prototype.getStartupConf = function() { + var params = this.connectionParameters; + + var data = { + user : params.user , + database : params.database + // client_encoding : "'".concat(params.client_encoding).concat("'") + }; + + var appName = params.application_name || params.fallback_application_name; + if (appName) { + data.application_name = appName; + } + + return data; +}; + Client.prototype.cancel = function(client, query) { if(client.activeQuery == query) { var con = this.connection; diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 1c3b0c30f..eef40d591 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -3,9 +3,17 @@ var path = require('path'); var defaults = require(__dirname + '/defaults'); -var val = function(key, config) { +var val = function(key, config, envVar) { + if (envVar === undefined) { + envVar = process.env[ 'PG' + key.toUpperCase() ]; + } else if (envVar === false) { + // do nothing ... use false + } else { + envVar = process.env[ envVar ]; + } + return config[key] || - process.env['PG' + key.toUpperCase()] || + envVar || defaults[key]; }; @@ -22,6 +30,14 @@ var parse = function(str) { if(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) str = encodeURI(str); var result = url.parse(str, true); config = {}; + + if (result.query.application_name) { + config.application_name = result.query.application_name; + } + if (result.query.fallback_application_name) { + config.fallback_application_name = result.query.fallback_application_name; + } + if(result.protocol == 'socket:') { config.host = decodeURI(result.pathname); config.database = result.query.db; @@ -68,6 +84,9 @@ var ConnectionParameters = function(config) { this.client_encoding = val("client_encoding", config); //a domain socket begins with '/' this.isDomainSocket = (!(this.host||'').indexOf('/')); + + this.application_name = val('application_name', config, 'PGAPPNAME'); + this.fallback_application_name = val('fallback_application_name', config, false); }; var add = function(params, config, paramName) { @@ -82,6 +101,9 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { add(params, this, 'user'); add(params, this, 'password'); add(params, this, 'port'); + add(params, this, 'application_name'); + add(params, this, 'fallback_application_name'); + if(this.database) { params.push("dbname='" + this.database + "'"); } diff --git a/lib/connection.js b/lib/connection.js index 6f230b1cd..0c5e96f2f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -117,16 +117,19 @@ Connection.prototype.requestSsl = function(config) { }; Connection.prototype.startup = function(config) { - var bodyBuffer = this.writer + var writer = this.writer .addInt16(3) .addInt16(0) - .addCString('user') - .addCString(config.user) - .addCString('database') - .addCString(config.database) - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('').flush(); + ; + + Object.keys(config).forEach(function(key){ + var val = config[key]; + writer.addCString(key).addCString(val); + }); + + writer.addCString('client_encoding').addCString("'utf-8'"); + + var bodyBuffer = writer.addCString('').flush(); //this message is sent without a code var length = bodyBuffer.length + 4; diff --git a/lib/defaults.js b/lib/defaults.js index a24c06cdd..1241703fd 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -38,7 +38,10 @@ var defaults = module.exports = { client_encoding: "", - ssl: false + ssl: false, + + application_name : undefined, + fallback_application_name: undefined }; //parse int8 so you can get your count values as actual numbers diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js new file mode 100644 index 000000000..c4da5087e --- /dev/null +++ b/test/integration/client/appname-tests.js @@ -0,0 +1,89 @@ +var helper = require('./test-helper'); +var Client = helper.Client; + +var conInfo = helper.config; + +function getConInfo(override) { + var newConInfo = {}; + Object.keys(conInfo).forEach(function(k){ + newConInfo[k] = conInfo[k]; + }); + Object.keys(override || {}).forEach(function(k){ + newConInfo[k] = override[k]; + }); + return newConInfo; +} + +function getAppName(conf, cb) { + var client = new Client(conf); + client.connect(assert.success(function(){ + client.query('SHOW application_name', assert.success(function(res){ + var appName = res.rows[0].application_name; + cb(appName); + client.end(); + })); + })); +} + +test('No default appliation_name ', function(){ + var conf = getConInfo(); + getAppName(conf, function(res){ + assert.strictEqual(res, ''); + }); +}); + +test('fallback_application_name is used', function(){ + var fbAppName = 'this is my app'; + var conf = getConInfo({ + 'fallback_application_name' : fbAppName + }); + getAppName(conf, function(res){ + assert.strictEqual(res, fbAppName); + }); +}); + +test('application_name is used', function(){ + var appName = 'some wired !@#$% application_name'; + var conf = getConInfo({ + 'application_name' : appName + }); + getAppName(conf, function(res){ + assert.strictEqual(res, appName); + }); +}); + +test('application_name has precedence over fallback_application_name', function(){ + var appName = 'some wired !@#$% application_name'; + var fbAppName = 'some other strange $$test$$ appname'; + var conf = getConInfo({ + 'application_name' : appName , + 'fallback_application_name' : fbAppName + }); + getAppName(conf, function(res){ + assert.strictEqual(res, appName); + }); +}); + +test('application_name from connection string', function(){ + var appName = 'my app'; + var conf = 'postgres:///?application_name='+appName; + getAppName(conf, function(res){ + assert.strictEqual(res, appName); + }); +}); + + + +// TODO: make the test work for native client too +if (!helper.args.native) { + test('application_name is read from the env', function(){ + var appName = process.env.PGAPPNAME = 'testest'; + var conf = getConInfo({ + 'just some bla' : 'to fool the pool' + }); + getAppName(conf, function(res){ + delete process.env.PGAPPNAME; + assert.strictEqual(res, appName); + }); + }); +} \ No newline at end of file From caffda67f2421179dc4a5e59beff036dd8ff164e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20H=C3=B6rl?= Date: Sun, 5 Jan 2014 18:26:42 +0100 Subject: [PATCH 2/3] change test to work on travis --- test/integration/client/appname-tests.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index c4da5087e..c68b694f8 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -66,7 +66,13 @@ test('application_name has precedence over fallback_application_name', function( test('application_name from connection string', function(){ var appName = 'my app'; - var conf = 'postgres:///?application_name='+appName; + var conParams = require(__dirname + '/../../../lib/connection-parameters'); + var conf; + if (process.argv[2]) { + conf = new conParams(process.argv[2]+'/?application_name='+appName); + } else { + conf = 'postgres://?application_name='+appName; + } getAppName(conf, function(res){ assert.strictEqual(res, appName); }); From 4f00e5ab1a0e317af85152c3084fc90e478373c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20H=C3=B6rl?= Date: Sun, 5 Jan 2014 18:29:30 +0100 Subject: [PATCH 3/3] typo --- test/integration/client/appname-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index c68b694f8..273536888 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -69,7 +69,7 @@ test('application_name from connection string', function(){ var conParams = require(__dirname + '/../../../lib/connection-parameters'); var conf; if (process.argv[2]) { - conf = new conParams(process.argv[2]+'/?application_name='+appName); + conf = new conParams(process.argv[2]+'?application_name='+appName); } else { conf = 'postgres://?application_name='+appName; }