Connect Remote Database on different server with mongoose - mongodb

I have a requirement where I have to connect two different databases on different remote servers with mongoose from my main server.
Now,I have done a bit of research and founded that we can connect multiple instance with mongoose and then can use useDb() to use the specific database.
Everything works fine when I am connecting it to 2 local database but when the database are remote and I am connecting it via IP it is giving authentication error.
I guess connections are getting mixed.
Below is my code that I am using which is working on local database:
mongoose.connect('mongodb://'+db.host+':'+db.port+'/'+db.dbname,{user: db.username, pass: db.password, useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true, useFindAndModify:false })
.then(() => {
console.log(`db connection successful`);
mongoose.connect('mongodb://'+db2.host+':'+db2.port+'/'+db2.dbname,{user: db2.username, pass: db2.password, useUnifiedTopology: true, useNewUrlParser: true, useCreateIndex: true, useFindAndModify:false })
.then(() => console.log(`db connection2 successful`))
.catch((err) => logger.error("db connection2 error", err));
}).catch((err) => logger.error("db connection1 error", err));
When host is localhost everything works fine but when I change it with the IP of the server it throws authentication error.
'not authorized on db to execute command { find: "collection_name", filter: { basicDetails.applicationNumber: "5000" }, projection: {}, returnKey: false, showRecordId: false, lsid: { id: UUID("164bf515-cec6-470f-fewcfrv") }, $clusterTime: { clusterTime: Timestamp(158461230, 1), signature: { hash: BinData(0, 6210C6E1586CFDBDC), keyId: 12346890 } }, $db: "DB" }'

Related

Can't connect to mongodb Atlas with typeorm

I'm trying to connect to a MongoDB Atlas database with typeORM in an express project but I'm getting a 'Unescaped slash in userinfo section' error. My password doesn't have any special characters that need to be encoded so I don't know what's going on.
import { DataSource } from "typeorm"
export const AppDataSource = new DataSource({
type: "mongodb",
host: "mongodb+srv://username:password#database.cluster.mongodb.net/?retryWrites=true&w=majority",
useNewUrlParser: true,
synchronize: true,
useUnifiedTopology: true,
logging: true,
ssl: true,
entities: [
"src/entity/*.ts"
],
subscribers: [],
migrations: [],
})
"use strict";
import express from "express";
import cors from 'cors';
import "reflect-metadata";
import { AppDataSource } from "./data-source";
AppDataSource.initialize().then(() => {
const app = express();
app.use(cors({
origin: ['http://localhost:3000'],
credentials: true // this will allow cookies to be sent accross domains
}));
app.listen(8080, () => {
console.log("Server is running on port 8080");
})
})
the error I'm getting :
return callback(new MongoParseError('Unescaped slash in userinfo section'));
^
MongoParseError: Unescaped slash in userinfo section
at parseConnectionString (D:\Personal\jamboit\backend\node_modules\mongodb\lib\core\uri_parser.js:627:21)
at connect (D:\Personal\jamboit\backend\node_modules\mongodb\lib\operations\connect.js:283:3)
at D:\Personal\jamboit\backend\node_modules\mongodb\lib\mongo_client.js:284:5
at maybePromise (D:\Personal\jamboit\backend\node_modules\mongodb\lib\utils.js:692:3)
at MongoClient.connect (D:\Personal\jamboit\backend\node_modules\mongodb\lib\mongo_client.js:280:10)
at Function.MongoClient.connect (D:\Personal\jamboit\backend\node_modules\mongodb\lib\mongo_client.js:426:22)
at D:\Personal\jamboit\backend\node_modules\typeorm\src\driver\mongodb\MongoDriver.ts:249:38
at new Promise (<anonymous>)
Just replace host params to url in DataSource options
export const AppDataSource = new DataSource({
type: "mongodb",
url: "mongodb+srv://username:password#database.cluster.mongodb.net/?retryWrites=true&w=majority",
useNewUrlParser: true,
synchronize: true,
useUnifiedTopology: true,
logging: true,
ssl: true,
entities: [
"src/entity/*.ts"
],
subscribers: [],
migrations: [],
})

Can't provoke MongoError - bad auth

Just to be clear, I want to get MongoError bad auth Authentication failed from MongoDB Atlas.
This is about wrong DB password and I'm trying to catch that error and act accordingly.
this is my connection method:
mongoose
.connect(CRED, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true
})
.then(() => {
console.log('connected to database');
});
and here I'm catching unhandledRejection error that supposed to catch wrong auth:
process.on('unhandledRejection', err => {
console.log(err.name, err.message);
server.close(() => {
process.exit(1);
});
});
If I put correct password, everything works fine and I'm connected to database.
But if I put wrong password, after 30 sec of waiting I get:
MongooseTimeoutError Server selection timed out after 30000 ms
...and this shouldn't suppose to work like that.
I should get MongoError (bad auth) immediately, on first attempt when app is connecting to MongoDB
...or am I doing something wrong?
It's known issue for Mongoose <=5.7.1 with useUnifiedTopology: true option.
Update your Mongoose to 5.9.2 to fix the issue.
With new version, Mongoose fails corectly:
MongooseServerSelectionError MongooseError [MongooseServerSelectionError]: Authentication failed.
at new MongooseServerSelectionError (D:\myapp\node_modules\mongoose\lib\error\serverSelection.js:22:11)
at NativeConnection.Connection.openUri (D:\myapp\node_modules\mongoose\lib\connection.js:808:32)
at Mongoose.connect (D:\myapp\node_modules\mongoose\lib\index.js:333:15)
at Object.<anonymous> (D:\myapp\app.js:46:10)
at Module._compile (internal/modules/cjs/loader.js:959:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
at Module.load (internal/modules/cjs/loader.js:815:32)
at Function.Module._load (internal/modules/cjs/loader.js:727:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
at internal/main/run_main_module.js:17:11 {
message: 'Authentication failed.',
name: 'MongooseServerSelectionError',
reason: TopologyDescription {
type: 'Single',
setName: null,
maxSetVersion: null,
maxElectionId: null,
servers: Map { 'localhost:27017' => [ServerDescription] },
stale: false,
compatible: true,
compatibilityError: null,
logicalSessionTimeoutMinutes: null,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: null
},
[Symbol(mongoErrorContextSymbol)]: {}
}
Also, add .catch clause to your code
mongoose
.connect(CRED, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true
})
.then(() => {
console.log('connected to database');
})
.catch(error => {
//MongooseServerSelectionError MongooseError [MongooseServerSelectionError]: Authentication failed
console.log("Error", error)
});

mongodb mongoose connection open callback doesnt get called

I have a MEAN project and this is a snippet from my server.js
var db = require('./config/db');
// url : 'mongodb://localhost/cdnserver'
// results are same for 127.0.0.1 or the machines ip
console.log(mongoose.connect(db.url));
mongoose.set('debug', true);
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to ' + db.url);
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
This is a setup that has been working well for over 3 months now. Now I am replicating my whole MEAN stack along with database to other machine. I took a mongodump and did mongorestore. The restored db setup looks fine through mongo from terminal.
However, when starting the server, connection-open callback is not getting called. disconnected and error callbacks are getting called if I stop the mongodb service. How do I debug this further?
I am attaching the console output from both the setups.
Setup 1 :
Mongoose {
connections:
[ NativeConnection {
base: [Circular],
collections: {},
models: {},
replica: false,
hosts: null,
host: 'localhost',
port: 27017,
user: undefined,
pass: undefined,
name: 'cdnserver',
options: [Object],
otherDbs: [],
_readyState: 2,
_closeCalled: false,
_hasOpened: false,
_listening: false,
db: [Object] } ],
plugins: [],
models: {},
modelSchemas: {},
options: { pluralization: true } }
Server up on 80
Mongoose default connection open to mongodb://localhost/cdnserver
1
Mongoose: videos.find({}) { skip: 0, limit: 5, fields: undefined }
Setup 2:
Mongoose {
connections:
[ NativeConnection {
base: [Circular],
collections: {},
models: {},
replica: false,
hosts: null,
host: 'localhost',
port: 27017,
user: undefined,
pass: undefined,
name: 'cdnserver',
options: [Object],
otherDbs: [],
_readyState: 2,
_closeCalled: false,
_hasOpened: false,
_listening: false,
db: [Object] } ],
plugins: [],
models: {},
modelSchemas: {},
options: { pluralization: true } }
Server up on 80
1
1
Mongoose default connection disconnected
Mongoose default connection error: Error: connection closed
cat /var/log/mongodb/mongodb.log shows exactly the same output in both the machines.
Update 1: The setup started working properly out of blue and it stopped again. I am not able to figure out what is making this happen.
I figured it out finally, the new setup was using a newer version of nodejs.
When I moved to 6.x from 7.x it worked fine. I guess the mongoose, node 7, mongodb versions didnt go well together.

Can't connect to mongodb from mocha test

Connecting from the REPL works fine:
> var mongoose=require('mongoose');
undefined
> mongoose.connect('mongodb://localhost/test', function(error) {
... console.log( 'connected\n%s\n', error );
... });
returns:
{ connections:
[ { base: [Circular],
collections: {},
models: {},
replica: false,
hosts: null,
host: 'localhost',
port: 27017,
user: undefined,
pass: undefined,
name: 'test',
options: [Object],
_readyState: 2,
_closeCalled: false,
_hasOpened: false,
_listening: false,
_events: {},
db: [Object] } ],
plugins: [],
models: {},
modelSchemas: {},
options: {} }
> connected # Yes!
undefined
But connecting from a Mocha test suite does not work:
var mongoose = require( 'mongoose' );
console.log( 'connecting...' );
mongoose.connect( 'mongodb://localhost/test', function( error ) {
if( error) console.error( 'Error while connecting:\n%\n', error );
console.log( 'connected' );
});
returns:
$ mocha
connecting...
0 passing (0 ms)
Does anyone know why this not working?
Do you have any tests in your suite? If not it seems like mocha exits before mongoose gets a chance to connect. One of the features listed on the mocha page is
auto-exit to prevent "hanging" with an active loop
which may have something to do with it. You could try connecting to mongoose in the before method of your test suite e.g.
describe('test suite', function() {
before(function(done) {
mongoose.connect('mongodb://localhost/test', function(error) {
if (error) console.error('Error while connecting:\n%\n', error);
console.log('connected');
done(error);
});
});
});

MongoDB+Nodejs reads are not distributed across replicaset members with readpreference as NEAREST

I had a replica set with primary/secondary and read preference as NEAREST. Through MongoStat, I can see that requests are going to the replica set member where the mongod instance and nodejs is running and not to the other member on a different aws instance. Pinging is not enabled between the two. I can also verify that the other instance is accessible by changing the read preference. Working fine with my java client. Should the other instance be ping-able for read sharing? SecondaryAcceptableLatencyMS is set at 500.
Here is the sample code snippet I am trying to execute.
var replSet = new ReplSetServers( [
new Server( "localhost", 27017, { auto_reconnect: true, native_parser: true, slaveOk: true } ),
new Server( "<replmem1>", 27017, { auto_reconnect: true, native_parser: true, slaveOk: true } ),
new Server( "<replmem2>", 27018, { auto_reconnect: true, native_parser: true, slaveOk: true } )
],
{read_secondary:true, secondaryAcceptableLatencyMS:500 }
);
var dbCon = new Db("emails_" + postParams["campaign_id"], replSet, {safe: true, readPreference: mongo.ReadPreference.NEAREST});
dbCon.open(function(err, db) {
Its not documented well yet but a strategy option must be specified when using NEAREST.
var replSet = new ReplSetServers( [
new Server( "localhost", 27017, { auto_reconnect: true, native_parser: true, slaveOk: true } ),
new Server( "<replmem1>", 27017, { auto_reconnect: true, native_parser: true, slaveOk: true } ),
new Server( "<replmem2>", 27018, { auto_reconnect: true, native_parser: true, slaveOk: true } )
],
{read_secondary:true, secondaryAcceptableLatencyMS:500, stragegy: 'ping' }
);
http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences