Opening and closing DB connection during API call [duplicate] - javascript

This question already has answers here:
Why is it recommended not to close a MongoDB connection anywhere in Node.js code?
(4 answers)
MongoDB - open and close connection - advise for good practice
(1 answer)
Closed 5 years ago.
My app.js looks below. mogoDBUtils.getMogoDbCon(); will open a db connection when new request comes in. I want to close the DB connection as soon as the api call to route.js is over.
Where do i need to place the code in app.js to close MongoDB connection in the below code so that upon evey new hit it opens a connection and close the connection after api call is completed.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.disable('x-powered-by')
var mogoDBUtils = require('./controller/utilities/mongodbutils.js')
var logger = require('./controller/utilities/logger.js'); //initialize logger class
require('./routes/route.js')(app); //define express router for api calls
mogoDBUtils.getMogoDbCon(); //open dbconnection
//setup server
var port = process.env.PORT || 80 // port
app.use(express.static('./views/webcontent/', { index: 'index.html' }))//define home page
app.listen(port);
console.log('Listening on port ' + port + '..');
// DB functions
module.exports.getMogoDbCon = function() {
new Promise((resolve, reject) => {
var mongoUri = getmongouri();
mongoose.connection.openUri(mongoUri);
var db = mongoose.connection;
db.on('error', function () {
throw new Error('unable to connect to database');
});
return resolve(db);
});
};
module.exports.closeMongoDBConnection = function () {
new Promise((resolve, reject) => {
mongoose.disconnect();
return resolve(true);
});
};

You can do it in a middleware. If you want to open and close connection on each request, you need to create two middlewares: for opening connection and for closing it:
I suppose that getMogoDbCon() and closeMogoDbCon return a promise, otherwise use callbacks.
app.use((req, res, next) => {
mogoDBUtils
.getMogoDbCon()
.then(conn => {
req.conn = conn;
next();
})
.catch(next);
});
require('./routes/route.js')(app); // define express router for api calls
app.use((req, res, next) => {
mogoDBUtils
.closeMogoDbCon(req.conn)
.then((() => next())
.catch(next);
});
Note about middleware order declaration. The middleware which opens connection must be defined firstly, after that all your routes, and the last one - the middleware which closes connection.

Related

Send variables to all routes in expressjs

I have req.session variables that I am setting upon login, like so:
req.session.loggedin = true
req.session.firstname = loginDetails.firstName;
what I want to do is pass this information to ALL routes (I have nearly 60, and don't want to go through all of them and add these in manually), and also every route I have calls the front-end using this:
res.render('page.ejs', {data: rows}), so I would ideally want it to pass it to the front-end pages so I can access them there too. Not sure if this is possible, but worth a shot! thx 4 the help in advance!
You can create a middleware function and add variables to an existing express-session.
app.js
const express = require("express");
const session = require("express-session");
// express app
const app = express();
app.use(express.json());
// init example session with express session
app.use(session({ resave: true, secret: "123456", saveUninitialized: true }));
// use a middleware function
app.use((req, res, next) => {
if (!req.session.initialised) {
// init variables you want to set in req.session
req.session.loggedin = true;
req.session.firstname = "john doe";
}
next();
});
// test api endpoint
app.use("/testroute", require("./routes/api/test"));
// run server
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
Then you can query your variables like req.session.firstname in any other route in the request object. You can also update it from your routes
test.js
// testroute
const router = express.Router();
router.get("/", async (req, res) => {
// get variables from request object
try {
console.log(req.session.firstname);
console.log(req.session.loggedin);
// this would update the session variable if uncommented
// req.session.firstname = "dagobert"
// console.log(req.session.firstname);
res.status(200).json({ message: `Your firstname is ${req.session.firstname}` });
} catch (error) {
res.status(400).json({ message: error.message });
}
});
module.exports = router;

HOW to implement backend with "EXPRESS" and frontend with "NUXT.JS"

I am new at web development and saying sorry for this question. THE thing is that i have done a serverside with Express and connected to MongoDB, have already established the connection where i can insert, select, delete information, but don't know how to make Frontend side with NUXT.JS, i want to put 4 buttons in frontend which will be select, insert, delete buttons . Here is my backend:
const express = require('express');
const bodyParser = require('body-parser');
// create express app
const app = express();
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }))
// parse requests of content-type - application/json
app.use(bodyParser.json())
// Configuring the database
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
// Connecting to the database
mongoose.connect(dbConfig.url, {
useNewUrlParser: true
}).then(() => {
console.log("Successfully connected to the database");
}).catch(err => {
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
});
// define a simple route
app.get('/', (req, res) => {
res.json({"message": "Welcome to EasyNotes application. Take notes quickly. Organize and keep track of all your notes."});
});
// Require Notes routes
require('./app/routes/note.routes.js')(app);
// listen for requests
app.listen(3000, () => {
console.log("Server is listening on port 3000");
});

How to send ws message from route request

I've been trying to create an app that uses telegram-bot, express server and react app. Therefore, I need to create a POST request from telegram-bot to express, while express sends POST data to a websocket connection:
const express = require("express");
const app = express();
const expressWs = require("express-ws")(app);
// handles bot request
app.post("/request", (req, res) => {
playlist.push(req.body.url);
res.status(200).send({ message: "video is added to playlist" });
});
// after handling requst data must go here and send ws message to client side
app.ws("/echo", (ws, req) => {
ws.on("message", msg => {
ws.send(`msg is = ${msg}`);
});
});
Am I making it right, and if so, how to call ws.send from after handling request at app.post route?
From the understanding I have from your question, here is an updated version of your code that does exactly what you want.
I replaced the express-ws package with ws since that would be sufficient for your use case.
The express server runs on port 8080 while the websocket server runs on port 8081 since are different protocols and would not run on the same port (You can make it work but I do not recommend it See this question
const express = require("express");
const Websocket = require('ws');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const wss = new Websocket.Server({ port: 8081 });
wss.on('connection', (ws) => {
console.log('One client connected');
ws.on("message", msg => {
ws.send(`msg is = ${msg}`);
});
})
// handles bot request
app.post("/request", (req, res) => {
// Broadcast URL to connected ws clients
wss.clients.forEach((client) => {
// Check that connect are open and still alive to avoid socket error
if (client.readyState === Websocket.OPEN) {
client.send(url);
}
});
res.status(200).send({ message: "video is added to playlist" });
});
app.listen(8080, () => {
console.log('Express listening on 8080');
console.log('Websocket on 8081');
});
Tested via curl with curl -d 'url=https://example.com/examplesong' localhost:8080/request I had a client connected to ws://localhost:8081 and everything looks good.

Continuously changing Express Route Paths for protection

I want to create a hidden internal webserver with ever-changing routes.
The aim is to prevent/deter people from scraping the site or using the API without permission.
There's probably a better way (or this could be totally useless)
I've written some code that works but either convince me why I'm wasting my time or why it would work.
const express = require('express');
const uuid = require('uuid/v4');
const app = express();
// These are the hidden routes
const routes = {
hiddenPage: undefined,
};
setInterval(() => {
// Change the path of the hidden page
// every 5 seconds
routes.hiddenPage = `/${uuid()}`;
}, 1000 * 5);
app.get('*', (req, res) => {
// There would be other middleware for
// security reasons
if (req.path === routes.hiddenPage) {
res.send('Welcome to the hidden page');
return;
}
res.send(`Page at <a href=${routes.hiddenPage}>${routes.hiddenPage}</a>`);
});
// Listen on 3000
app.listen(3000);
You can use CORS middleware to allow only specific clients to access your server.
https://expressjs.com/en/resources/middleware/cors.html
Example:
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})

Temporary 'loading' route in Express?

I have a web app that takes a moment to load - as it needs to connect to a database, and so some other things that take time.
What's the best way to have a temporary loading route in Express?
I'd like to do something like the following:
const express = require('express')
const app = express()
// Temporary / for if someone hits the server before it's finished starting
app.get('/', (req, res) => res.send(`Loading....`))
// In my non-demo app, there's a router here that takes a moment to load, instead of a timeout.
setTimeout(function(){
app.get('/', (req, res) => res.send(`Ready!`))
}, 3 * 1000)
app.listen(3000, () => console.log('Example app listening on port 3000!'))
Routes can't be deleted at runtime, but you can add a middleware that checks if everything is initialized, if it isn't you end the request with: res.send('Loading'); otherwise you go to the next middelware.
let initialized = false;
app.get('/', (req, res, next) => {
if(!initialized)
return res.send('Loading...');
next();
});
app.get('/', (req, res, next) => {
res.send(`Ready!`);
});
setTimeout(() => initialized = true, 3000);
If your app needs some time to load properly, the best option is to NOT let it start the server.
It works very well with i.e. load balancers and multiple containers as they wait for the /health check to pass before they put the container behind the loadbalancer. Which is something you want to do for modern services.
For example this:
import { app } from './app';
import { config } from './config';
import { logger } from './components/ourLog';
import { initPromise } from './components/ourMongo';
const port = config.server.port;
async function startServer() {
await initPromise;
app.listen(port, () => {
logger.info(
{
port,
params: config.params,
processEnv: process.env,
},
'App has started'
);
});
}
startServer()
.catch(err => {
logger.error({ err }, 'Critical error, cannot start server');
process.exit(1);
});
We have component that connects to mongo and it expose initPromise, which is the promise, which is resolved after the connection is sucesfully done and you can start with using the db.
You could ping the server "x" seconds to test when it is ready.
Server
We will create a ready variable, that is set to false, when all of your database, api and other things are done doing what they need you set it to true.
We will also create a route that such as /ping that will respond with the value of ready.
const express = require('express')
const app = express()
let ready = false
// Do database stuff, API stuff, etc.
// Set ready to true when ready
// Temporary / for if someone hits the server before it's finished starting
app.get('/', (req, res) => res.send(`Loading....`))
app.get('/ping', (req, res) => res.json({ready}))
app.listen(3000, () => console.log('Example app listening on port 3000!'))
Client
Here we will ping the server every "x" seconds, I set it to 0.5s, once ping returns true, we cancel the timeout and run the initialization code that builds the page.
let timeout
timeout = setInterval(async () => {
let response = await fetch('/ping')
let ready = await response.json()
if (ready.ready) {
clearInterval(timeout)
loadpage()
}
}, 500)

Categories