Source: lib/mongo_client.js

  1. "use strict";
  2. var parse = require('./url_parser')
  3. , Server = require('./server')
  4. , Mongos = require('./mongos')
  5. , ReplSet = require('./replset')
  6. , EventEmitter = require('events').EventEmitter
  7. , inherits = require('util').inherits
  8. , Define = require('./metadata')
  9. , ReadPreference = require('./read_preference')
  10. , Logger = require('mongodb-core').Logger
  11. , MongoError = require('mongodb-core').MongoError
  12. , Db = require('./db')
  13. , f = require('util').format
  14. , assign = require('./utils').assign
  15. , shallowClone = require('./utils').shallowClone
  16. , authenticate = require('./authenticate');
  17. /**
  18. * @fileOverview The **MongoClient** class is a class that allows for making Connections to MongoDB.
  19. *
  20. * @example
  21. * var MongoClient = require('mongodb').MongoClient,
  22. * test = require('assert');
  23. * // Connection url
  24. * var url = 'mongodb://localhost:27017/test';
  25. * // Connect using MongoClient
  26. * MongoClient.connect(url, function(err, db) {
  27. * // Get an additional db
  28. * db.close();
  29. * });
  30. */
  31. var validOptionNames = ['poolSize', 'ssl', 'sslValidate', 'sslCA', 'sslCert', 'ciphers', 'ecdhCurve',
  32. 'sslKey', 'sslPass', 'sslCRL', 'autoReconnect', 'noDelay', 'keepAlive', 'connectTimeoutMS', 'family',
  33. 'socketTimeoutMS', 'reconnectTries', 'reconnectInterval', 'ha', 'haInterval',
  34. 'replicaSet', 'secondaryAcceptableLatencyMS', 'acceptableLatencyMS',
  35. 'connectWithNoPrimary', 'authSource', 'w', 'wtimeout', 'j', 'forceServerObjectId',
  36. 'serializeFunctions', 'ignoreUndefined', 'raw', 'bufferMaxEntries',
  37. 'readPreference', 'pkFactory', 'promiseLibrary', 'readConcern', 'maxStalenessSeconds',
  38. 'loggerLevel', 'logger', 'promoteValues', 'promoteBuffers', 'promoteLongs',
  39. 'domainsEnabled', 'keepAliveInitialDelay', 'checkServerIdentity', 'validateOptions', 'appname', 'auth'];
  40. var ignoreOptionNames = ['native_parser'];
  41. var legacyOptionNames = ['server', 'replset', 'replSet', 'mongos', 'db'];
  42. function validOptions(options) {
  43. var _validOptions = validOptionNames.concat(legacyOptionNames);
  44. for(var name in options) {
  45. if(ignoreOptionNames.indexOf(name) != -1) {
  46. continue;
  47. }
  48. if(_validOptions.indexOf(name) == -1 && options.validateOptions) {
  49. return new MongoError(f('option %s is not supported', name));
  50. } else if(_validOptions.indexOf(name) == -1) {
  51. console.warn(f('the options [%s] is not supported', name));
  52. }
  53. if(legacyOptionNames.indexOf(name) != -1) {
  54. console.warn(f('the server/replset/mongos options are deprecated, '
  55. + 'all their options are supported at the top level of the options object [%s]', validOptionNames));
  56. }
  57. }
  58. }
  59. /**
  60. * Creates a new MongoClient instance
  61. * @class
  62. * @return {MongoClient} a MongoClient instance.
  63. */
  64. function MongoClient() {
  65. if(!(this instanceof MongoClient)) return new MongoClient();
  66. // Set up event emitter
  67. EventEmitter.call(this);
  68. /**
  69. * The callback format for results
  70. * @callback MongoClient~connectCallback
  71. * @param {MongoError} error An error instance representing the error during the execution.
  72. * @param {Db} db The connected database.
  73. */
  74. /**
  75. * Connect to MongoDB using a url as documented at
  76. *
  77. * docs.mongodb.org/manual/reference/connection-string/
  78. *
  79. * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver
  80. *
  81. * @method
  82. * @param {string} url The connection URI string
  83. * @param {object} [options] Optional settings.
  84. * @param {number} [options.poolSize=5] poolSize The maximum size of the individual server pool.
  85. * @param {boolean} [options.ssl=false] Enable SSL connection.
  86. * @param {Buffer} [options.sslCA=undefined] SSL Certificate store binary buffer
  87. * @param {Buffer} [options.sslCRL=undefined] SSL Certificate revocation list binary buffer
  88. * @param {Buffer} [options.sslCert=undefined] SSL Certificate binary buffer
  89. * @param {Buffer} [options.sslKey=undefined] SSL Key file binary buffer
  90. * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase
  91. * @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.
  92. * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
  93. * @param {boolean} [options.noDelay=true] TCP Connection no delay
  94. * @param {number} [options.family=4] Version of IP stack. Defaults to 4.
  95. * @param {number} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
  96. * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting
  97. * @param {number} [options.socketTimeoutMS=360000] TCP Socket timeout setting
  98. * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
  99. * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
  100. * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies.
  101. * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry
  102. * @param {string} [options.replicaSet=undefined] The Replicaset set name
  103. * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection
  104. * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection.
  105. * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
  106. * @param {string} [options.authSource=undefined] Define the database to authenticate against
  107. * @param {string} [options.auth.user=undefined] The username for auth
  108. * @param {string} [options.auth.password=undefined] The password for auth
  109. * @param {(number|string)} [options.w=null] The write concern.
  110. * @param {number} [options.wtimeout=null] The write concern timeout.
  111. * @param {boolean} [options.j=false] Specify a journal write concern.
  112. * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver.
  113. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
  114. * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
  115. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  116. * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
  117. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
  118. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
  119. * @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.
  120. * @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  121. * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
  122. * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys.
  123. * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
  124. * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
  125. * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
  126. * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
  127. * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections.
  128. * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
  129. * @param {object} [options.logger=undefined] Custom logger object
  130. * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness.
  131. * @param {MongoClient~connectCallback} [callback] The command result callback
  132. * @return {Promise} returns Promise if no callback passed
  133. */
  134. this.connect = MongoClient.connect;
  135. }
  136. /**
  137. * @ignore
  138. */
  139. inherits(MongoClient, EventEmitter);
  140. var define = MongoClient.define = new Define('MongoClient', MongoClient, false);
  141. /**
  142. * Connect to MongoDB using a url as documented at
  143. *
  144. * docs.mongodb.org/manual/reference/connection-string/
  145. *
  146. * Note that for replicasets the replicaSet query parameter is required in the 2.0 driver
  147. *
  148. * @method
  149. * @static
  150. * @param {string} url The connection URI string
  151. * @param {object} [options] Optional settings.
  152. * @param {number} [options.poolSize=5] poolSize The maximum size of the individual server pool.
  153. * @param {boolean} [options.ssl=false] Enable SSL connection.
  154. * @param {Buffer} [options.sslCA=undefined] SSL Certificate store binary buffer
  155. * @param {Buffer} [options.sslCRL=undefined] SSL Certificate revocation list binary buffer
  156. * @param {Buffer} [options.sslCert=undefined] SSL Certificate binary buffer
  157. * @param {Buffer} [options.sslKey=undefined] SSL Key file binary buffer
  158. * @param {string} [options.sslPass=undefined] SSL Certificate pass phrase
  159. * @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.
  160. * @param {boolean} [options.autoReconnect=true] Enable autoReconnect for single server instances
  161. * @param {boolean} [options.noDelay=true] TCP Connection no delay
  162. * @param {number} [options.family=4] Version of IP stack. Defaults to 4.
  163. * @param {boolean} [options.keepAlive=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket.
  164. * @param {number} [options.connectTimeoutMS=30000] TCP Connection timeout setting
  165. * @param {number} [options.socketTimeoutMS=360000] TCP Socket timeout setting
  166. * @param {number} [options.reconnectTries=30] Server attempt to reconnect #times
  167. * @param {number} [options.reconnectInterval=1000] Server will wait # milliseconds between retries
  168. * @param {boolean} [options.ha=true] Control if high availability monitoring runs for Replicaset or Mongos proxies.
  169. * @param {number} [options.haInterval=10000] The High availability period for replicaset inquiry
  170. * @param {string} [options.replicaSet=undefined] The Replicaset set name
  171. * @param {number} [options.secondaryAcceptableLatencyMS=15] Cutoff latency point in MS for Replicaset member selection
  172. * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for Mongos proxies selection.
  173. * @param {boolean} [options.connectWithNoPrimary=false] Sets if the driver should connect even if no primary is available
  174. * @param {string} [options.authSource=undefined] Define the database to authenticate against
  175. * @param {string} [options.auth.user=undefined] The username for auth
  176. * @param {string} [options.auth.password=undefined] The password for auth
  177. * @param {(number|string)} [options.w=null] The write concern.
  178. * @param {number} [options.wtimeout=null] The write concern timeout.
  179. * @param {boolean} [options.j=false] Specify a journal write concern.
  180. * @param {boolean} [options.forceServerObjectId=false] Force server to assign _id values instead of driver.
  181. * @param {boolean} [options.serializeFunctions=false] Serialize functions on any object.
  182. * @param {Boolean} [options.ignoreUndefined=false] Specify if the BSON serializer should ignore undefined fields.
  183. * @param {boolean} [options.raw=false] Return document results as raw BSON buffers.
  184. * @param {boolean} [options.promoteLongs=true] Promotes Long values to number if they fit inside the 53 bits resolution.
  185. * @param {boolean} [options.promoteBuffers=false] Promotes Binary BSON values to native Node Buffers.
  186. * @param {boolean} [options.promoteValues=true] Promotes BSON values to native types where possible, set to false to only receive wrapper types.
  187. * @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.
  188. * @param {(ReadPreference|string)} [options.readPreference=null] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
  189. * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
  190. * @param {object} [options.pkFactory=null] A primary key factory object for generation of custom _id keys.
  191. * @param {object} [options.promiseLibrary=null] A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible
  192. * @param {object} [options.readConcern=null] Specify a read concern for the collection. (only MongoDB 3.2 or higher supported)
  193. * @param {string} [options.readConcern.level='local'] Specify a read concern level for the collection operations, one of [local|majority]. (only MongoDB 3.2 or higher supported)
  194. * @param {number} [options.maxStalenessSeconds=undefined] The max staleness to secondary reads (values under 10 seconds cannot be guaranteed);
  195. * @param {string} [options.appname=undefined] The name of the application that created this MongoClient instance. MongoDB 3.4 and newer will print this value in the server log upon establishing each connection. It is also recorded in the slow query log and profile collections.
  196. * @param {string} [options.loggerLevel=undefined] The logging level (error/warn/info/debug)
  197. * @param {object} [options.logger=undefined] Custom logger object
  198. * @param {object} [options.validateOptions=false] Validate MongoClient passed in options for correctness.
  199. * @param {MongoClient~connectCallback} [callback] The command result callback
  200. * @return {Promise} returns Promise if no callback passed
  201. */
  202. MongoClient.connect = function(url, options, callback) {
  203. var args = Array.prototype.slice.call(arguments, 1);
  204. callback = typeof args[args.length - 1] == 'function' ? args.pop() : null;
  205. options = args.length ? args.shift() : null;
  206. options = options || {};
  207. var self = this;
  208. // Validate options object
  209. var err = validOptions(options);
  210. // Get the promiseLibrary
  211. var promiseLibrary = options.promiseLibrary;
  212. // No promise library selected fall back
  213. if(!promiseLibrary) {
  214. promiseLibrary = typeof global.Promise == 'function' ?
  215. global.Promise : require('es6-promise').Promise;
  216. }
  217. // Return a promise
  218. if(typeof callback != 'function') {
  219. return new promiseLibrary(function(resolve, reject) {
  220. // Did we have a validation error
  221. if(err) return reject(err);
  222. // Attempt to connect
  223. connect(self, url, options, function(err, db) {
  224. if(err) return reject(err);
  225. resolve(db);
  226. });
  227. });
  228. }
  229. // Did we have a validation error
  230. if(err) return callback(err);
  231. // Fallback to callback based connect
  232. connect(self, url, options, callback);
  233. }
  234. define.staticMethod('connect', {callback: true, promise:true});
  235. var mergeOptions = function(target, source, flatten) {
  236. for(var name in source) {
  237. if(source[name] && typeof source[name] == 'object' && flatten) {
  238. target = mergeOptions(target, source[name], flatten);
  239. } else {
  240. target[name] = source[name];
  241. }
  242. }
  243. return target;
  244. }
  245. var createUnifiedOptions = function(finalOptions, options) {
  246. var childOptions = ['mongos', 'server', 'db'
  247. , 'replset', 'db_options', 'server_options', 'rs_options', 'mongos_options'];
  248. var noMerge = ['readconcern'];
  249. for(var name in options) {
  250. if(noMerge.indexOf(name.toLowerCase()) != -1) {
  251. finalOptions[name] = options[name];
  252. } else if(childOptions.indexOf(name.toLowerCase()) != -1) {
  253. finalOptions = mergeOptions(finalOptions, options[name], false);
  254. } else {
  255. if(options[name] && typeof options[name] == 'object' && !Buffer.isBuffer(options[name]) && !Array.isArray(options[name])) {
  256. finalOptions = mergeOptions(finalOptions, options[name], true);
  257. } else {
  258. finalOptions[name] = options[name];
  259. }
  260. }
  261. }
  262. return finalOptions;
  263. }
  264. function translateOptions(options) {
  265. // If we have a readPreference passed in by the db options
  266. if(typeof options.readPreference == 'string' || typeof options.read_preference == 'string') {
  267. options.readPreference = new ReadPreference(options.readPreference || options.read_preference);
  268. }
  269. // Do we have readPreference tags, add them
  270. if(options.readPreference && (options.readPreferenceTags || options.read_preference_tags)) {
  271. options.readPreference.tags = options.readPreferenceTags || options.read_preference_tags;
  272. }
  273. // Do we have maxStalenessSeconds
  274. if(options.maxStalenessSeconds) {
  275. options.readPreference.maxStalenessSeconds = options.maxStalenessSeconds;
  276. }
  277. // Set the socket and connection timeouts
  278. if(options.socketTimeoutMS == null) options.socketTimeoutMS = 360000;
  279. if(options.connectTimeoutMS == null) options.connectTimeoutMS = 30000;
  280. // Create server instances
  281. return options.servers.map(function(serverObj) {
  282. return serverObj.domain_socket ?
  283. new Server(serverObj.domain_socket, 27017, options)
  284. : new Server(serverObj.host, serverObj.port, options);
  285. });
  286. }
  287. //
  288. // Collect all events in order from SDAM
  289. //
  290. function collectEvents(self, db) {
  291. var collectedEvents = [];
  292. if(self instanceof MongoClient) {
  293. var events = ["timeout", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
  294. 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
  295. 'topologyClosed', 'topologyDescriptionChanged', 'joined', 'left', 'ping', 'ha', 'all', 'fullsetup'];
  296. events.forEach(function(event) {
  297. db.serverConfig.on(event, function(object1, object2) {
  298. collectedEvents.push({
  299. event: event, object1: object1, object2: object2
  300. });
  301. });
  302. });
  303. }
  304. return collectedEvents;
  305. }
  306. //
  307. // Replay any events due to single server connection switching to Mongos
  308. //
  309. function replayEvents(self, events) {
  310. for(var i = 0; i < events.length; i++) {
  311. self.emit(events[i].event, events[i].object1, events[i].object2);
  312. }
  313. }
  314. function relayEvents(self, db) {
  315. if(self instanceof MongoClient) {
  316. var events = ["timeout", "close", 'serverOpening', 'serverDescriptionChanged', 'serverHeartbeatStarted',
  317. 'serverHeartbeatSucceeded', 'serverHeartbeatFailed', 'serverClosed', 'topologyOpening',
  318. 'topologyClosed', 'topologyDescriptionChanged', 'joined', 'left', 'ping', 'ha', 'all', 'fullsetup'];
  319. events.forEach(function(event) {
  320. db.serverConfig.on(event, function(object1, object2) {
  321. self.emit(event, object1, object2);
  322. });
  323. });
  324. }
  325. }
  326. function createReplicaset(self, options, callback) {
  327. // Set default options
  328. var servers = translateOptions(options);
  329. // Create Db instance
  330. var db = new Db(options.dbName, new ReplSet(servers, options), options);
  331. // Propegate the events to the client
  332. relayEvents(self, db);
  333. // Open the connection
  334. db.open(callback);
  335. }
  336. function createMongos(self, options, callback) {
  337. // Set default options
  338. var servers = translateOptions(options);
  339. // Create Db instance
  340. var db = new Db(options.dbName, new Mongos(servers, options), options)
  341. // Propegate the events to the client
  342. relayEvents(self, db);
  343. // Open the connection
  344. db.open(callback);
  345. }
  346. function createServer(self, options, callback) {
  347. // Set default options
  348. var servers = translateOptions(options);
  349. // Create db instance
  350. var db = new Db(options.dbName, servers[0], options);
  351. // Propegate the events to the client
  352. var collectedEvents = collectEvents(self, db);
  353. // Create Db instance
  354. db.open(function(err, db) {
  355. if(err) return callback(err);
  356. // Check if we are really speaking to a mongos
  357. var ismaster = db.serverConfig.lastIsMaster();
  358. // Do we actually have a mongos
  359. if(ismaster && ismaster.msg == 'isdbgrid') {
  360. // Destroy the current connection
  361. db.close();
  362. // Create mongos connection instead
  363. return createMongos(self, options, callback);
  364. }
  365. // Fire all the events
  366. replayEvents(self, collectedEvents);
  367. // Propegate the events to the client
  368. relayEvents(self, db);
  369. // Otherwise callback
  370. callback(err, db);
  371. });
  372. }
  373. function connectHandler(options, callback) {
  374. return function (err, db) {
  375. if(err) {
  376. return process.nextTick(function() {
  377. try {
  378. callback(err, null);
  379. } catch (err) {
  380. if(db) db.close();
  381. throw err
  382. }
  383. });
  384. }
  385. // No authentication just reconnect
  386. if(!options.auth) {
  387. return process.nextTick(function() {
  388. try {
  389. callback(err, db);
  390. } catch (err) {
  391. if(db) db.close();
  392. throw err
  393. }
  394. })
  395. }
  396. // What db to authenticate against
  397. var authentication_db = db;
  398. if(options.authSource) {
  399. authentication_db = db.db(options.authSource);
  400. }
  401. // Authenticate
  402. authenticate(authentication_db, options.user, options.password, options, function(err, success) {
  403. if(success){
  404. process.nextTick(function() {
  405. try {
  406. callback(null, db);
  407. } catch (err) {
  408. if(db) db.close();
  409. throw err
  410. }
  411. });
  412. } else {
  413. if(db) db.close();
  414. process.nextTick(function() {
  415. try {
  416. callback(err ? err : new Error('Could not authenticate user ' + options.auth[0]), null);
  417. } catch (err) {
  418. if(db) db.close();
  419. throw err
  420. }
  421. });
  422. }
  423. });
  424. }
  425. }
  426. /*
  427. * Connect using MongoClient
  428. */
  429. var connect = function(self, url, options, callback) {
  430. options = options || {};
  431. options = shallowClone(options);
  432. // If callback is null throw an exception
  433. if(callback == null) {
  434. throw new Error("no callback function provided");
  435. }
  436. // Get a logger for MongoClient
  437. var logger = Logger('MongoClient', options);
  438. parse(url, options, function(err, object) {
  439. if (err) return callback(err);
  440. // Parse the string
  441. var _finalOptions = createUnifiedOptions({}, object);
  442. _finalOptions = mergeOptions(_finalOptions, object, false);
  443. _finalOptions = createUnifiedOptions(_finalOptions, options);
  444. // Check if we have connection and socket timeout set
  445. if(_finalOptions.socketTimeoutMS == null) _finalOptions.socketTimeoutMS = 360000;
  446. if(_finalOptions.connectTimeoutMS == null) _finalOptions.connectTimeoutMS = 30000;
  447. if (_finalOptions.db_options && _finalOptions.db_options.auth) {
  448. delete _finalOptions.db_options.auth;
  449. }
  450. // Failure modes
  451. if(object.servers.length == 0) {
  452. throw new Error("connection string must contain at least one seed host");
  453. }
  454. // Do we have a replicaset then skip discovery and go straight to connectivity
  455. if(_finalOptions.replicaSet || _finalOptions.rs_name) {
  456. return createReplicaset(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
  457. } else if(object.servers.length > 1) {
  458. return createMongos(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
  459. } else {
  460. return createServer(self, _finalOptions, connectHandler(_finalOptions, connectCallback));
  461. }
  462. });
  463. function connectCallback(err, db) {
  464. if(err && err.message == 'no mongos proxies found in seed list') {
  465. if(logger.isWarn()) {
  466. logger.warn(f('seed list contains no mongos proxies, replicaset connections requires the parameter replicaSet to be supplied in the URI or options object, mongodb://server:port/db?replicaSet=name'));
  467. }
  468. // Return a more specific error message for MongoClient.connect
  469. return callback(new MongoError('seed list contains no mongos proxies, replicaset connections requires the parameter replicaSet to be supplied in the URI or options object, mongodb://server:port/db?replicaSet=name'));
  470. }
  471. // Return the error and db instance
  472. callback(err, db);
  473. }
  474. }
  475. module.exports = MongoClient