diff --git a/docs/reference/content/reference/connecting/connection-settings.md b/docs/reference/content/reference/connecting/connection-settings.md index 8f00fd90a6..ff0bd934a9 100644 --- a/docs/reference/content/reference/connecting/connection-settings.md +++ b/docs/reference/content/reference/connecting/connection-settings.md @@ -63,12 +63,17 @@ The table below shows all settings and what topology they affect. | **ignoreUndefined** | Server, ReplicaSet, Mongos | boolean | false | Specify if the BSON serializer should ignore undefined fields. | | **raw** | Server, ReplicaSet, Mongos | boolean | false | Return document results as raw BSON buffers. | | **promoteLongs** | Server, ReplicaSet, Mongos | boolean | true | Promotes Long values to number if they fit inside the 53 bits resolution. | +| **promoteBuffers** | Server, ReplicaSet, Mongos | boolean | false | Promotes Binary BSON values to native Node Buffers. | +| **promoteValues** | Server, ReplicaSet, Mongos | boolean | true | Promotes BSON values to native types where possible, set to false to only receive wrapper types. | +| **domainsEnabled** | Server, ReplicaSet, Mongos | boolean | false | Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. | | **bufferMaxEntries** | Server, ReplicaSet, Mongos | integer | -1 | Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited. | | **readPreference** | Server, ReplicaSet, Mongos | object | null | The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). | | **pkFactory** | Server, ReplicaSet, Mongos | object | null | A primary key factory object for generation of custom _id keys. | | **promiseLibrary** | Server, ReplicaSet, Mongos | object | null | A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible. | | **readConcern** | Server, ReplicaSet, Mongos | object | null | Specify a read concern for the collection. (only MongoDB 3.2 or higher supported). | | **maxStalenessSeconds** | Replicaset | number | null | Specify a maxStalenessSeconds value for secondary reads, minimum is 90 seconds | +| **loggerLevel** | Server, Replicaset, Mongos | string | null | Specify the log level used by the driver logger (error/warn/info/debug) | +| **logger** | Server, Replicaset, Mongos | object | null | Specify a customer logger mechanism, can be used to log using your app level logger | # Ensure you connection string is valid for Replica Sets The connection string passed to the driver must use the fully qualified host names for the servers as set in the replicaset config. Given the following configuration settings for your replicaset. diff --git a/lib/mongo_client.js b/lib/mongo_client.js index 55421d913f..05d22fc712 100644 --- a/lib/mongo_client.js +++ b/lib/mongo_client.js @@ -26,6 +26,36 @@ var parse = require('./url_parser') * db.close(); * }); */ +var validOptionNames = ['poolSize', 'ssl', 'sslValidate', 'sslCA', 'sslCert', + 'sslKey', 'sslPass', 'autoReconnect', 'noDelay', 'keepAlive', 'connectTimeoutMS', + 'socketTimeoutMS', 'reconnectTries', 'reconnectInterval', 'ha', 'haInterval', + 'replicaSet', 'secondaryAcceptableLatencyMS', 'acceptableLatencyMS', + 'connectWithNoPrimary', 'authSource', 'w', 'wtimeout', 'j', 'forceServerObjectId', + 'serializeFunctions', 'ignoreUndefined', 'raw', 'promoteLongs', 'bufferMaxEntries', + 'readPreference', 'pkFactory', 'promiseLibrary', 'readConcern', 'maxStalenessSeconds', + 'loggerLevel', 'logger', 'promoteValues', 'promoteBuffers', 'promoteLongs', + 'domainsEnabled', 'keepAliveInitialDelay', 'checkServerIdentity']; +var ignoreOptionNames = ['native_parser']; +var legacyOptionNames = ['server', 'replset', 'mongos', 'db']; + +function validOptions(options) { + var _validOptions = validOptionNames.concat(legacyOptionNames); + + for(var name in options) { + if(ignoreOptionNames.indexOf(name) != -1) { + continue; + } + + if(_validOptions.indexOf(name) == -1) { + return new MongoError(f('option %s is not supported', name)); + } + + if(legacyOptionNames.indexOf(name) == -1) { + console.warn(f('the server/replset/mongos options are deprecated, ' + + 'all their options are supported at the top level of the options object [%s]', validOptionNames)); + } + } +} /** * Creates a new MongoClient instance @@ -49,13 +79,48 @@ function MongoClient() { * * @method * @param {string} url The connection URI string - * @param {object} [options=null] Optional settings. - * @param {boolean} [options.uri_decode_auth=false] Uri decode the user name and password for authentication - * @param {object} [options.db=null] A hash of options to set on the db object, see **Db constructor** - * @param {object} [options.server=null] A hash of options to set on the server objects, see **Server** constructor** - * @param {object} [options.replSet=null] A hash of options to set on the replSet object, see **ReplSet** constructor** - * @param {object} [options.mongos=null] A hash of options to set on the mongos object, see **Mongos** constructor** + * @param {object} [options] Optional settings. + * @param {number} [options.poolSize=5] poolSize The maximum size of the individual server pool. + * @param {boolean} [options.ssl=false] Enable SSL connection. + * @param {Buffer} [options.sslCA=undefined] SSL Certificate store binary buffer + * @param {Buffer} [options.sslCert=undefined] SSL Certificate binary buffer + * @param {Buffer} [options.sslKey=undefined] SSL Key file binary buffer + * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase + * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function. + * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances + * @param {boolean} [options.noDelay=true] TCP Connection no delay + * @param {boolean} [options.keepAlive=0] The number of milliseconds to wait before initiating keepAlive on the TCP socket. + * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting + * @param {number} [options.socketTimeoutMS=30000] TCP Socket timeout setting + * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times + * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries + * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies. + * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry + * @param {string} [options.replicaSet=undefined] The Replicaset set name + * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection + * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection. + * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available + * @param {string} [options.authSource=undefined] Define the database to authenticate against + * @param {(number|string)} [options.w=null] The write concern. + * @param {number} [options.wtimeout=null] The write concern timeout. + * @param {boolean} [options.j=false] Specify a journal write concern. + * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver. + * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object. + * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields. + * @param {boolean} [options.raw=false] Return document results as raw BSON buffers. + * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution. + * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers. + * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types. + * @param {number} [options.bufferMaxEntries=-1] Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited. + * @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. + * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys. * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible + * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported) + * @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported) + * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed); + * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug) + * @param {object} [options.logger=undefined] Custom logger object * @param {MongoClient~connectCallback} [callback] The command result callback * @return {Promise} returns Promise if no callback passed */ @@ -74,13 +139,48 @@ var define = MongoClient.define = new Define('MongoClient', MongoClient, false); * @method * @static * @param {string} url The connection URI string - * @param {object} [options=null] Optional settings. - * @param {boolean} [options.uri_decode_auth=false] Uri decode the user name and password for authentication - * @param {object} [options.db=null] A hash of options to set on the db object, see **Db constructor** - * @param {object} [options.server=null] A hash of options to set on the server objects, see **Server** constructor** - * @param {object} [options.replSet=null] A hash of options to set on the replSet object, see **ReplSet** constructor** - * @param {object} [options.mongos=null] A hash of options to set on the mongos object, see **Mongos** constructor** + * @param {object} [options] Optional settings. + * @param {number} [options.poolSize=5] poolSize The maximum size of the individual server pool. + * @param {boolean} [options.ssl=false] Enable SSL connection. + * @param {Buffer} [options.sslCA=undefined] SSL Certificate store binary buffer + * @param {Buffer} [options.sslCert=undefined] SSL Certificate binary buffer + * @param {Buffer} [options.sslKey=undefined] SSL Key file binary buffer + * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase + * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function. + * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances + * @param {boolean} [options.noDelay=true] TCP Connection no delay + * @param {boolean} [options.keepAlive=0] The number of milliseconds to wait before initiating keepAlive on the TCP socket. + * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting + * @param {number} [options.socketTimeoutMS=30000] TCP Socket timeout setting + * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times + * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries + * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies. + * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry + * @param {string} [options.replicaSet=undefined] The Replicaset set name + * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection + * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection. + * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available + * @param {string} [options.authSource=undefined] Define the database to authenticate against + * @param {(number|string)} [options.w=null] The write concern. + * @param {number} [options.wtimeout=null] The write concern timeout. + * @param {boolean} [options.j=false] Specify a journal write concern. + * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver. + * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object. + * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields. + * @param {boolean} [options.raw=false] Return document results as raw BSON buffers. + * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution. + * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers. + * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types. + * @param {number} [options.bufferMaxEntries=-1] Sets a cap on how many operations the driver will buffer up before giving up on getting a working connection, default is -1 which is unlimited. + * @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). + * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. + * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys. * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible + * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported) + * @param {object} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported) + * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed); + * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug) + * @param {object} [options.logger=undefined] Custom logger object * @param {MongoClient~connectCallback} [callback] The command result callback * @return {Promise} returns Promise if no callback passed */ @@ -90,6 +190,9 @@ MongoClient.connect = function(url, options, callback) { options = args.length ? args.shift() : null; options = options || {}; + // Validate options object + var err = validOptions(options); + // Get the promiseLibrary var promiseLibrary = options.promiseLibrary; @@ -102,6 +205,9 @@ MongoClient.connect = function(url, options, callback) { // Return a promise if(typeof callback != 'function') { return new promiseLibrary(function(resolve, reject) { + // Did we have a validation error + if(err) return reject(err); + // Attempt to connect connect(url, options, function(err, db) { if(err) return reject(err); resolve(db); @@ -109,6 +215,8 @@ MongoClient.connect = function(url, options, callback) { }); } + // Did we have a validation error + if(err) return callback(err); // Fallback to callback based connect connect(url, options, callback); } diff --git a/lib/replset.js b/lib/replset.js index 84c29c9ebe..ae7b7b89cf 100644 --- a/lib/replset.js +++ b/lib/replset.js @@ -45,7 +45,7 @@ var legalOptionNames = ['ha', 'haInterval', 'replicaSet', 'rs_name', 'secondaryA , 'store', 'auto_reconnect', 'autoReconnect', 'emitError' , 'keepAlive', 'noDelay', 'connectTimeoutMS', 'socketTimeoutMS', 'strategy', 'debug' , 'loggerLevel', 'logger', 'reconnectTries', 'appname', 'domainsEnabled' - , 'servername', 'promoteLongs', 'promoteValues', 'promoteBuffers']; + , 'servername', 'promoteLongs', 'promoteValues', 'promoteBuffers', 'maxStalenessSeconds']; // Get package.json variable var driverVersion = require(__dirname + '/../package.json').version; @@ -81,6 +81,7 @@ var release = os.release(); * @param {number} [options.socketOptions.connectTimeoutMS=10000] TCP Connection timeout setting * @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit. + * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed); * @fires ReplSet#connect * @fires ReplSet#ha * @fires ReplSet#joined diff --git a/test/functional/authentication_tests.js b/test/functional/authentication_tests.js index d5a6a1dc1f..b588460b97 100644 --- a/test/functional/authentication_tests.js +++ b/test/functional/authentication_tests.js @@ -658,6 +658,7 @@ var setUp = function(configuration, options, callback) { dbpath: f('%s/../db/31001', __dirname), } }, { + // arbiter: true, options: { bind_ip: 'localhost', port: 31002, dbpath: f('%s/../db/31002', __dirname), @@ -718,6 +719,7 @@ exports['Should correctly handle replicaset master stepdown and stepup without l // Add a user db.admin().addUser("root", "root", {w:3, wtimeout: 25000}, function(err, result) { test.equal(null, err); + // process.exit(0) db.admin().authenticate("root", "root", function(err, result) { test.equal(null, err); diff --git a/test/functional/mongo_client_options_tests.js b/test/functional/mongo_client_options_tests.js index 5a7e6e4cb0..ffdae1fc8d 100644 --- a/test/functional/mongo_client_options_tests.js +++ b/test/functional/mongo_client_options_tests.js @@ -20,6 +20,47 @@ exports['pass in server and db top level options'] = { } } +/** + * @ignore + */ +exports['pass in server and db top level options'] = { + metadata: { requires: { topology: 'single' } }, + + // The actual test we wish to run + test: function(configuration, test) { + var connect = configuration.require; + + connect(configuration.url(), + { autoReconnect: true, poolSize: 4 }, + connectionTester(test, 'testConnectServerOptions', function(db) { + test.equal(1, db.serverConfig.poolSize); + test.equal(4, db.serverConfig.s.server.s.pool.size); + test.equal(true, db.serverConfig.autoReconnect); + db.close(); + test.done(); + })); + } +} + +/** + * @ignore + */ +exports['should error on unexpected options'] = { + metadata: { requires: { topology: 'single' } }, + + // The actual test we wish to run + test: function(configuration, test) { + var connect = configuration.require; + + connect(configuration.url(), { + autoReconnect: true, poolSize: 4, notlegal: {} + }, function(err, db) { + test.ok(err.message.indexOf('option notlegal is not supported') != -1); + test.done(); + }); + } +} + /** * @ignore */ diff --git a/test/functional/uri_tests.js b/test/functional/uri_tests.js index 3dd5500e98..e857b7da47 100644 --- a/test/functional/uri_tests.js +++ b/test/functional/uri_tests.js @@ -187,7 +187,7 @@ exports['Should correctly connect using uri encoded username and password'] = { db.addUser(user, pass, function(err) { test.equal(null, err); var uri = "mongodb://" + encodeURIComponent(user) + ":" + encodeURIComponent(pass) + "@localhost:27017/integration_tests"; - MongoClient.connect(uri, {uri_decode_auth: true, native_parser:true}, function(err, authenticatedDb) { + MongoClient.connect(uri, {native_parser:true}, function(err, authenticatedDb) { test.equal(null, err); db.close();