Skip to content

Commit

Permalink
Use a third-party URL parser
Browse files Browse the repository at this point in the history
The `url.parse` from the standard lib provides the username and
password as one field, and decodes them. This means any
percent-encoded characters are decoded, and it's impossible to tell
whether a colon is the delimiter between the username and password, or
was encoded and part of one or other.

Newer versions of the Node standard library come with an updated URL
parser. However, I would like to work with older versions of Node, so
I've used a third party parser.
  • Loading branch information
squaremo committed Nov 15, 2017
1 parent be11b7d commit 7acbfd7
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 24 deletions.
22 changes: 6 additions & 16 deletions lib/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

'use strict';

var URL = require('url');
var URL = require('url-parse');
var QS = require('querystring');
var Connection = require('./connection').Connection;
var fmt = require('util').format;
Expand Down Expand Up @@ -76,22 +76,12 @@ function openFrames(vhost, query, credentials, extraClientProperties) {
};
}

// Decide on credentials based on what we're supplied. Note that in a
// parsed URL, the auth part is already URL-decoded, so e.g., '%3a' in
// the URL is already decoded to ':'. This is a bit unhelpful, as it
// means we can't tell whether a colon is a separator, or part of the
// username. Assume no colons in usernames.
// Decide on credentials based on what we're supplied.
function credentialsFromUrl(parts) {
var user = 'guest', passwd = 'guest';
if (parts.auth) {
var colon = parts.auth.indexOf(':')
if (colon == -1) {
user = parts.auth;
passwd = '';
} else {
user = parts.auth.substring(0, colon);
passwd = parts.auth.substring(colon+1);
}
if (parts.username != '' || parts.password != '') {
user = (parts.username) ? unescape(parts.username) : '';
passwd = (parts.password) ? unescape(parts.password) : '';
}
return credentials.plain(user, passwd);
}
Expand Down Expand Up @@ -137,7 +127,7 @@ function connect(url, socketOptions, openCallback) {

fields = openFrames(url.vhost, config, sockopts.credentials || credentials.plain(user, pass), extraClientProperties);
} else {
var parts = URL.parse(url, true); // yes, parse the query string
var parts = URL(url, true); // yes, parse the query string
protocol = parts.protocol;
sockopts.host = parts.hostname;
sockopts.port = parseInt(parts.port) || ((protocol === 'amqp:') ? 5672 : 5671);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"bluebird": "^3.4.6",
"buffer-more-ints": "0.0.2",
"readable-stream": "1.x >=1.1.9",
"safe-buffer": "^5.0.1"
"safe-buffer": "^5.0.1",
"url-parse": "^1.2.0"
},
"devDependencies": {
"mocha": "~1",
Expand Down
16 changes: 9 additions & 7 deletions test/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ var format = require('util').format;

var URL = process.env.URL || 'amqp://localhost';

var urlparse = require('url-parse');

suite("Credentials", function() {

function checkCreds(creds, user, pass, done) {
Expand All @@ -27,29 +29,29 @@ suite("Credentials", function() {
}

test("no creds", function(done) {
var parts = {auth: ''};
var parts = urlparse('amqp://localhost');
var creds = credentialsFromUrl(parts);
checkCreds(creds, 'guest', 'guest', done);
});
test("usual user:pass", function(done) {
var parts = {auth: 'user:pass'};
var parts = urlparse('amqp://user:pass@localhost')
var creds = credentialsFromUrl(parts);
checkCreds(creds, 'user', 'pass', done);
});
test("missing user", function(done) {
var parts = {auth: ':password'};
var parts = urlparse('amqps://:password@localhost');
var creds = credentialsFromUrl(parts);
checkCreds(creds, '', 'password', done);
});
test("missing password", function(done) {
var parts = {auth: 'username'};
var parts = urlparse('amqps://username:@localhost');
var creds = credentialsFromUrl(parts);
checkCreds(creds, 'username', '', done);
});
test("colon in password", function(done) {
var parts = {auth: 'username:pass:word'};
test("escaped colons", function(done) {
var parts = urlparse('amqp://user%3Aname:pass%3Aword@localhost')
var creds = credentialsFromUrl(parts);
checkCreds(creds, 'username', 'pass:word', done);
checkCreds(creds, 'user:name', 'pass:word', done);
});
});

Expand Down

0 comments on commit 7acbfd7

Please sign in to comment.