Charles HETIER
Charles HETIER

Reputation: 2074

get express params in an intercepting middleware

I would like to intercept a req.params item in an interception layer:

let's say I have an express server application instance:

const app = express();

with an interception layer:

app.use((req, res, next) => {
    console.log(req.params.myParam);
    next();
})

and many endpoints like this one:

app.get('/anything/:myParam', (req, res) => res.send('hello'))

this logs 'undefined' which is quite natural because when the interception middleware within the "use" is executed, the param name has not been defined yet. But I really need to known in this interception layer the value of myParam parameter with these constraints:

Does anyone know a solution for that case ?

Upvotes: 1

Views: 369

Answers (3)

Charles HETIER
Charles HETIER

Reputation: 2074

The comment from @indrajaj26 about using app.param() leads me on a working solution.

Here is the way I'm proceeding:

/** express application */
const app = express();

// Interception layer
app.param('myParam', (req, res, next, myParam) => {
/* Store myParam into something reusable (like locals as suggested by @nullromo for instance).
 * I'm using zonejs in my case: creating a forked zone with myParam stored in zone properties.
 */
    next();
});

// Consuming intercepted data. Anywhere in the callstack of any endpoint using "myParam" as request parameter:
console.log(Zone.current.getZoneWith('myParam')?.get('myParam'));

Thanks everyone for your ideas!

Upvotes: 1

nullromo
nullromo

Reputation: 2647

You can store the params on the response.locals object for use by later middleware.

const express = require('express');

const app = express();

app.get('/:name', (request, response, next) => {
    // generate some kind of result
    const result = `Hello, ${request.params.name ?? 'world'}!`;
    // save the result and the params onto the request.locals object
    response.locals = { params: request.params, result };
    // call the next middleware to pass on the params and result
    next();
});

app.use((request, response, next) => {
    // here you have the params since they were parsed by the previous middleware
    console.log(`Intercepted: ${JSON.stringify(response.locals.params)}`);
    // now actually send the response that you wanted to send
    response.status(200).send(response.locals.result);
});

app.listen(3000, () => {
    console.log('listening');
});

This requires storing the request.params on the response.locals object in every handler, which is not the greatest. But it also means that you don't have to specify the interceptor middleware every time, if that's a problem for your case.

Upvotes: 0

Tyler2P
Tyler2P

Reputation: 2370

A simple solution would be to pass the middleware function when defining the route.

Example:

function middleware(req, res, next) {
    console.log(req.params.myParam);
    next();
}

app.get('/path', middleware, function(req, res) {
    ...
});

Full example:

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

function middleware(req, res, next) {
    console.log(req.params.myParam);
    next();
}

app.get('/path', middleware, function(req, res) {
    ...
});

app.listen(3000, () => console.log('server is online'));

Upvotes: 0

Related Questions