Handling parameters in Express middleware

I'm trying to figure out how to structure my Express code, and am confused about how to handle parameters. For sake of example let's imagine that I've written some middleware that loads something from the database:

var loadMW = function (request, response, next) {
    var thingID = request.params.id;
    // load thing from db and put in locals
    response.locals.thing = loadThing(id); //sync for simplicity
    next();
}

This is all good when used in a route like:

app.get('/getThing/:id', loadMW, ...)

Let's imagine, though, that I'd also like to have routes which accept the thing's ID in the request body (I know in this case this appears contrived, but it does come up for real).

app.post('/getThing', loadMW, ...)

That's not going to work, because loadMW expect to look in the request.params. What is the best way to structure the code in this case? I can think of a few alternatives. First would be to define a new middleware:

var loadMWBody = function (request, response, next) {
     var id = request.body.id;
     ...
}

This seems needlessly verbose and a bit ugly.

Another would be to modify the loadMW to always look to the locals for the ID, and then explicitly move the parameters in the routes.

var loadMW = function (request, response, next) {
    var thingID = response.locals.id;
    // load thing from db and put in locals
    response.locals.thing = loadThing(id); //sync for simplicity
    next();
}

app.get('/getThing/:id', function (request, response, next) {
           response.locals.id = request.params.id;
           next();
         },
   loadMW,
   ...)

app.post('/getThing', function (request, response, next) {
           response.locals.id = request.body.id;
           next();
         },
   loadMW,
   ...)

This seems ok, although again is a little bit verbose, and seems a bit mechanical.

I feel like I might be missing something, and that there's a more elegant way to do this. I thought about parameterising the middleware with some sort of function that indicates how to get the parameter, but this isn't really straightforward (as the request isn't in scope at the point of definition).

Anybody got a nice solution to this problem?

There's another way of handling this.

var loadMW = function (request, response, next) {
    var thingID = request.param('id');

    // load thing from db and put in locals
    response.locals.thing = loadThing(id); //sync for simplicity
    next();
}

The documentation for request.param() says that it looks for parameters in order of:

  1. req.paramsexpress.bodyParse()
  2. req.body
  3. req.query

I believe that the req.body section depends on having express.bodyParser() used at some point.

Something like the followig is won't do the trick?

var loadMW = function (request, response, next) {
    var thingID;
    if(request.param.id) {
        thingID = request.param.id;
    }
    else {
        thingID = request.body.id;
    }
    // load thing from db and put in locals
    response.locals.thing = loadThing(thingID); //sync for simplicity
    next();
}

You can also have a look to the optional params in express, for less verbosity, given the following route '/user/:id?' the id param is optional.

And have a look to http://expressjs.com/api.html#app.use for middlewares.

If it were my project, this is probs how I'd go about it:

The route handlers encapsulate the knowledge of how the params come from the client, and loadMW just knows how to get it (and serve it – in this example).

app.get('/getThing/:id', function(req, res) { loadMW(req.params, res); });
app.post('/getThing', function(req, res) { loadMW(req.body, res); });

function loadMW(opts, response) {
  var thingId = opts.id;
  ...
}

As the project grows, it may make sense to further abstract loadMW by passing in a callback function as the 2nd param – rather than response.