Search code examples
node.jsexpressmiddleware

Pass object to routes file used as middleware in nodejs


When my application starts, an object is created that is used throughout the app in multiple files. In my app.js file I am requiring several files that contain my routes. These routes need access to the object created in app.js so I'm trying to pass it to each of these files. An example of one of the files is below.

test.js

const express = require('express');
const router = express.Router();

router.use('/api', router);

router.post('/testRoute', (req, res, next) => {
    if(globalVariable.abc) { //globalVariable is the variable created in app.js
        //do some logic
    }
    res.json({
        message: "Test Route Success"
    })    
});

module.exports = router;

app.js

const assessmentRoutes = require('./routes/test');
app.use(assessmentRoutes);

One way I've tried to get the variable passed in is wrapping the routes in test.js in a function that takes the variable like this.

module.exports = function(globalVariable) {
    router.post('/testRoute', (req, res, next) => {
    if(globalVariable.abc) { //globalVariable is the variable created in app.js
        //do some logic
    }
    res.json({
        message: "Test Route Success"
    })    
});
}

Then in app.js the require changes to:

const assessmentRoutes = require('./routes/assessments')(globalVariable);

When I do it this way I get errors starting the application like app.use() requires a middleware function.

How to I pass the object into my routes?


Solution

  • 🙅 Using the global object

    One approach, which I don't recommend, is using the global object:

    app.js

    const assessmentRoutes = require('./routes/test');
    
    global.globalVariable = { abc: ... };
    
    app.use(assessmentRoutes);
    

    test.js

    const express = require('express');
    const router = express.Router();
    
    router.post('/testRoute', (req, res, next) => {
    
        if (globalVariable.abc) { ... }
    
        res.json({
            message: 'Test Route Success',
        });
    });
    
    module.exports = router;
    

    ✨ Export a function and pass in options

    Another approach is to export a function where you can pass in that as a param, as you did. The problem is that you are not returning the router from that function, that you later need to use in app.js:

    app.js

    const assessmentRoutes = require('./routes/test');
    
    app.use(assessmentRoutes({ abc: ... }));
    

    test.js

    const express = require('express');
    const router = express.Router();
    
    module.exports = function(globalVariable) {
    
        router.post('/testRoute', (req, res, next) => {
    
            if (globalVariable.abc) { ... }
    
            res.json({
                message: 'Test Route Success',
            });
        });
    
        // 👇 This is what you were missing in your code!
        return router;
    };
    

    ✨ Export the router and a setter function

    A similar option would be to export the router object as well as a setter function to initialise globalVariable inside test.js:

    app.js

    const { assessmentRoutes, initAssessmentRoutes } = require('./routes/test');
    
    initAssessmentRoutes({ abc: ... });
    
    app.use(assessmentRoutes);
    

    test.js

    const express = require('express');
    const router = express.Router();
    
    let globalVariable = { abc: null };
    
    function initAssessmentRoutes(options) {
        globalVariable = options;
    }
    
    router.post('/testRoute', (req, res, next) => {
    
        if (globalVariable.abc) { ... }
    
        res.json({
            message: 'Test Route Success',
        });
    });
    
    module.exports = {
        assessmentRoutes: router,
        initAssessmentRoutes,
    };