Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

142
Views
What is the best practice to pass db and logger to routes in Express

Using Express, to pass single instance references like a logger and/or db to routes, I see three options currently.

First is to attach it to the request object via a middleware:

app.use(function(req,res,next){
req.db = db; //this db comes from app.js context where you define it
next();
});

or in app as:

app.set('db', db) // db was previously set
...
app.get('user/:id', users.getUser);

then inside your route function call to use:

module.export.getUser = (req,res) {
...
req.app.get('db').user.find(request.params.id)

Next way is to call some init method on the controller, ie:

const users = require('user.js);
... //setup logger, setup db, then call:
users.init(logger,db); // init method sets local logger/database inside user.js

Last is a variation on the above which forces init to happen once when the module is required:

// setup db and logger, then later call:
require('user.js')(db, logger) //not great style-wise by not having all requires near the top of doc

and in your user.js, set your export like so:

module.exports = (db, logger) => { // returning public functions

This is what I really hate about vanilla JS, and even a framework like Express. It's part of the reason why frameworks like React are so popular because there are set ways to do things or at least commonly accepted patterns.

Ok, back to the topic. What's the best practice for passing single instance things like a logger and database to all your routes/controllers? One of the above or something better?

Unfortunately if you search for "express best practices for routers", you'll get dozens of variations. Is there some goto reference/bible? Some best practice or best pattern guide?

Thanks for any advise/feedback, Paul

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

index.js

const express = require('express');
const app = express();

require('./startup/logging')(app);
require('./startup/routes')(app);
require('./startup/db')();

const config = require('./startup/config');

const server = app.listen(config.app.port, () => console.log(`Listening on port ${config.app.port}...`));
module.exports = server;

startup/logging.js

const morgan = require('morgan');

module.exports = function (app) {
 app.use(morgan('tiny'));
}

startup/db

const mongoose = require('mongoose');
const config = require('./config');

module.exports = function () {
  mongoose.connect(config.db.uri, config.db.parameters)
    .then(() => console.log(`Connected to ${config.db.uri}...`));
}

startup/config.js

require('dotenv').config();

const env = process.env.NODE_ENV || 'dev';

const config = {
    'dev': {
        app: {
            port: parseInt(process.env.DEV_APP_PORT),
        },
        db: {
            uri: process.env.DEV_APP_DB,
            parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }
        },
    },
    'test': {
        app: {
            port: parseInt(process.env.TEST_APP_PORT),
        },
        db: {
            uri: process.env.TEST_APP_DB,
            parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }
        },
    },
    'prod': {
        app: {
            port: parseInt(process.env.PROD_APP_PORT),
        },
        db: {
            uri: process.env.PROD_APP_DB,
            parameters: { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }
        },
    }
}

module.exports = config[env];

startup/routes.js

const express = require('express');
const users = require('user.js);

module.exports = function (app) {
  app.use('/api/users', users);
}

routes/users.js

const auth = require('../middleware/auth');
const express = require('express');
const router = express.Router();

router.get('/users', auth, async (req, res) => {
  res.send([{name: 'paul', name: 'john'}]);
});

module.exports = router;

middleware/auth

require('dotenv').config();
const jwt = require('jsonwebtoken');

module.exports = function (req, res, next) {
  const token = req.header('x-auth-token');
  if (!token) return res.status(401).send('Access denied. No token provided.');

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  }
  catch (ex) {
    res.status(400).send('Invalid token.');
  }
}

.dotenv

NODE_ENV = 'dev'

DEV_APP_PORT = 5000
TEST_APP_PORT = 4000
PROD_APP_PORT = 3000

DEV_APP_DB = 'mongodb://localhost:27017/example_dev'
TEST_APP_DB = 'mongodb://localhost:27017/example_test'
PROD_APP_DB = 'mongodb://localhost:27017/example'
JWT_SECRET = 'yourJwtSecretKey'
about 4 years ago · Juan Pablo Isaza Report

0

I'm confused as to why you would want to perform dependency injection through the routing framework. I've always thought of those as two completely separate layers, express that deals with http requests and then delegates to the logic underneath. Where that logic can be an IOC container of DI'd modules or whatever you want. In JS you can create classes which require dependencies, and then modules which export implementations of those dependencies. The modules will be single impls of those dependencies, letting you spin up whatever combos you want. Do yeah, I don't think express should know anything about your architecture or dependencies, it should simply map routes to service layer functions.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!