123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- // muri
- /**
- * MongoDB URI parser as described here:
- * http://www.mongodb.org/display/DOCS/Connections
- */
- /**
- * Module dependencies
- */
- var qs = require('querystring');
- /**
- * Defaults
- */
- var DEFAULT_PORT = 27017;
- var DEFAULT_DB = 'test';
- var ADMIN_DB = 'admin';
- /**
- * Muri
- */
- module.exports = exports = function muri (str) {
- if (!/^mongodb:\/\//.test(str)) {
- throw new Error('Invalid mongodb uri "' + str + '". Must begin with "mongodb://"');
- }
- var ret = {
- hosts: []
- , db: DEFAULT_DB
- , options: {}
- }
- var match = /^mongodb:\/\/([^?]+)(\??.*)$/.exec(str);
- if (!match || '/' == match[1]) {
- throw new Error('Invalid mongodb uri "' + str + '". Missing hostname');
- }
- var uris = match[1];
- var path = match[2];
- var db;
- uris.split(',').forEach(function (uri) {
- var o = parse(uri);
- if (o.host) {
- ret.hosts.push({
- host: o.host
- , port: parseInt(o.port, 10)
- })
- if (!db && o.db) {
- db = o.db;
- }
- } else if (o.ipc) {
- ret.hosts.push({ ipc: o.ipc });
- }
- if (o.auth) {
- ret.auth = {
- user: o.auth.user ? (o.auth.user) : void 0
- , pass: o.auth.pass ? (o.auth.pass) : void 0
- }
- }
- })
- if (!ret.hosts.length) {
- throw new Error('Invalid mongodb uri "' + str + '". Missing hostname');
- }
- var parts = path.split('?');
- if (!db) {
- if (parts[0]) {
- db = parts[0].replace(/^\//, '');
- } else {
- // deal with ipc formats
- db = /\/([^\.]+)$/.exec(match[1]);
- if (db && db[1]) {
- db = db[1];
- }
- }
- }
- if (db) {
- ret.db = db;
- } else if (ret.auth) {
- ret.db = ADMIN_DB;
- }
- if (parts[1]) {
- ret.options = options(parts[1]);
- }
- return ret;
- }
- /**
- * Parse str into key/val pairs casting values appropriately.
- */
- function options (str) {
- var sep = /;/.test(str)
- ? ';'
- : '&';
- var ret = qs.parse(str, sep);
- Object.keys(ret).forEach(function (key) {
- var val = ret[key];
- if ('readPreferenceTags' == key) {
- val = readPref(val);
- if (val) {
- ret[key] = Array.isArray(val)
- ? val
- : [val];
- }
- } else {
- ret[key] = format(val);
- }
- });
- return ret;
- }
- function format (val) {
- var num;
- if ('true' == val) {
- return true;
- } else if ('false' == val) {
- return false;
- } else {
- num = parseInt(+val, 10);
- if (!isNaN(num)) {
- return num;
- }
- }
- return val;
- }
- function readPref (val) {
- var ret;
- if (Array.isArray(val)) {
- ret = val.map(readPref).filter(Boolean);
- return ret.length
- ? ret
- : undefined
- }
- var pair = val.split(',');
- var hasKeys;
- ret = {};
- pair.forEach(function (kv) {
- kv = (kv || '').trim();
- if (!kv) return;
- hasKeys = true;
- var split = kv.split(':');
- ret[split[0]] = format(split[1]);
- });
- return hasKeys && ret;
- }
- var ipcRgx = /\.sock/;
- function parse (uriString) {
- // do not use require('url').parse b/c it can't handle # in username or pwd
- // mongo uris are strange
- var uri = uriString;
- var ret = {};
- var parts;
- var auth;
- var ipcs;
- // skip protocol
- uri = uri.replace(/^mongodb:\/\//, '');
- // auth
- if (/@/.test(uri)) {
- parts = uri.split(/@/);
- auth = parts[0];
- uri = parts[1];
- parts = auth.split(':');
- ret.auth = {};
- ret.auth.user = decodeURIComponent(parts[0]);
- ret.auth.pass = parts[1] ? decodeURIComponent(parts[1]) : void 0;
- }
- // unix domain sockets
- if (ipcRgx.test(uri)) {
- ipcs = uri.split(ipcRgx);
- ret.ipc = ipcs[0] + '.sock';
- // included a database?
- if (ipcs[1]) {
- // strip leading / from database name
- ipcs[1] = ipcs[1].replace(/^\//, '');
- if (ipcs[1]) {
- ret.db = ipcs[1];
- }
- }
- return ret;
- }
- // database name
- parts = uri.split('/');
- if (parts[1]) ret.db = parts[1];
- // ipv6, [ip]:host
- if (/^\[[^\]]+\]:\d+/.test(parts[0])) {
- ret.host = parts[0].substring(1, parts[0].indexOf(']:'));
- ret.port = parts[0].substring(parts[0].indexOf(']:') + ']:'.length);
- } else {
- // host:port
- parts = parts[0].split(':');
- ret.host = parts[0];
- ret.port = parts[1] || DEFAULT_PORT;
- }
- return ret;
- }
- /**
- * Version
- */
- module.exports.version = require('../package.json').version;
|