Search code examples
javascriptexpressdependency-injectionmiddleware

Dependency Injection in ExpressJS Routing Middleware


Hi I'm trying to inject some dependencies in to an expressjs route middleware.

Normally in your main app you'd do:

const express = require('express');
const userRouter = require('./routes/users.js');
const app = express();
app.use('/users', userRouter);

And in your users.js you'd have something like:

const express = require('express');
const router = express.Router()
router.post('/user', function (req, res, next) {...}
router.get('/user/:id', function (req, res, next) {...}
router.put('/user/:id', function (req, res, next) {...}
router.delete('/user/:id', function (req, res, next) {...}

But I'd like to pass in some dependencies, e.g. a service URL, and its not clear from the docs how to do this, I thought something like:

const express = require('express');

function userRoutes(options) {
    const router = express.Router();

    router.post('/user', function (req, res, next) {...}
    router.get('/user/:id', function (req, res, next) {...}
    router.put('/user/:id', function (req, res, next) {...}
    router.delete('/user/:id', function (req, res, next) {...}

    return router
}

module.exports.userRoutes = userRoutes;

and then in my main app use it like:

const userRouter = require('./routes/users.js');
const app = express();
app.use('/users', userRouter.userRoutes(options));

but I get:

Users/jm/Private/Projects/api-gateway/node_modules/express/lib/router/index.js:458
  throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
  ^

TypeError: Router.use() requires a middleware function but got a undefined
at Function.use (/Users/jm/Private/Projects/api-gateway/node_modules/express/lib/router/index.js:458:13)
at EventEmitter.<anonymous> (/Users/jm/Private/Projects/api-gateway/node_modules/express/lib/application.js:220:21)
at Array.forEach (native)
at EventEmitter.use (/Users/jm/Private/Projects/api-gateway/node_modules/express/lib/application.js:217:7)
at Object.<anonymous> (/Users/jm/Private/Projects/api-gateway/app.js:28:5)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)

Any suggestions/solutions appreciated.


Solution

  • I've tried your code and it's working for me. These are my files, just in case it helps.

    package.json:

    {
      "name": "problem",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node index.js"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "express": "^4.16.4"
      }
    }
    

    index.js

    const express = require('express');
    const http = require('http');
    
    const userRouter = require('./routes/users.js');
    const app = express();
    const options = {};
    app.use('/users', userRouter.userRoutes(options));
    
    const server = http.createServer(app);
    server.listen(3000);
    console.log('listening on port 3000');
    

    routes/users.js

    const express = require('express');
    
    function userRoutes(options) {
        const router = express.Router();
    
        router.post('/user', function (req, res, next) {res.json({done:true})})
        router.get('/user/:id', function (req, res, next) {res.json({done:true})})
        router.put('/user/:id', function (req, res, next) {res.json({done:true})})
        router.delete('/user/:id', function (req, res, next) {res.json({done:true})})
    
        return router
    }
    
    module.exports.userRoutes = userRoutes;
    

    When I run npm start it start listening in port 3000. And it starts.