Brandon Lewis Brandon Lewis - 5 months ago 18
Node.js Question

Creating a Modular REST API in ExpressJS

I'm having some trouble creating a RESTful API in Node/Express. In the app I'm building, a user has many messages, and messages belong to users. I need to be able to make an HTTP requests to retrieve all messages by a particular user. Here's the basic structure of the app, starting with the basic server, which delegates routing to a file called 'config/middleware.js'.

//server.js

var express = require('express');
var bodyParser = require('body-parser');

var app = express();

require('./config/middleware.js')(app, express);

var port = process.env.PORT || 8080;

app.use(bodyParser.json());
app.use(express.static(__dirname + '/../client'));

app.listen(port);


This is the middleware file where we send requests to the appropriate router. A request made to 'users/5/messages' would get routed to the messages router, and a request made to 'users/5' would get routed to the users router.

// config/middleware.js

module.exports = function(app, express) {
var usersRouter = express.Router();
var messagesRouter = express.Router();

app.use('/users/:userId/messages', messagesRouter);
app.use('/users', usersRouter);

require('../routers/users')(usersRouter);
require('../routers/messages')(messagesRouter);
};


This is the messages router. If a get request is made to '/users/5/messages', I want the getAllMessages function to be run, which should return all messages by the user with userId 5.

// routers/messages.js

var messagesController = require('../controllers/messages');

module.exports = function(app) {
app.get('/:messageId', messagesController.getMessage);
app.get('/', messagesController.getAllMessages);
};


The problem is that the getAllMessages function doesn't have access to the 'userId' parameter (with value of 5), which is required in order to make an appropriate query to the database. The getAllMessages function in the controller expects the userId to be stored on req.params.userId. Is there any way to get the userId of 5 to be present on the req.params object inside the getAllMessages function?

Answer

The req.params are not passed down the route chain. To do so, you could do something like

In server.js, create a key on req. This will pass on your data between routes. Do this before mounting the routes.

app.use(function (req, res, next) {
  req._data = {};

  next();
});

In config/middleware.js,

    module.exports = function(app, express) {
  var usersRouter = express.Router();
  var messagesRouter = express.Router();

  // attach usedId
  app.use('/users/:userId/messages', function (req, res, next) {
        req._data.userId = req.params.userId;
        next();
  });

  // mount the router
  app.use('/users/:userId/messages', messagesRouter);
  app.use('/users', usersRouter);

  require('../routers/users')(usersRouter);
  require('../routers/messages')(messagesRouter);
};

This way, you would have access to req._data.userId in routers/messages.js.

Side note: A better way to structure the routes would be to use something like, (read shameless plug), https://github.com/swarajgiri/express-bootstrap/blob/master/web/routes.js

Comments