Reputation: 61
I want to have a middleware like Express log request summary end of each route =>
[POST] /books/commentpart 200 1435.472 ms - 35
I want to log more data in end of each request. But I do not know how to write middleware like this. I have tried a middleware function after all route but it not worked. In each router, I also pass next() call.
app.use(responseTime());
//router
app
.use(users(app, db))
.use(dataLogs(app, db))
.use(category(app, db));
//log middleware
app.use(function(req, res, next) {
var data = {};
var method = req.method;
if(method == 'GET'){
data = req.query;
} else {
data = req.body;
}
var resTime = res.getHeader('X-Response-Time');
log.debug(' [ ' + iduser + ' ] - ' + req.route.path + ' - ' + resTime + ' : ' + JSON.stringify(data));
});
module.exports = app;
Upvotes: 5
Views: 4632
Reputation: 11
Consider using async / await
const lastMiddleware = async (req, res, next) => {
// Allow the route handler to run first and wait for it to be completed
await next();
// Do work
}
Upvotes: 0
Reputation: 29927
So, middlewares, when registered (using app.use
, app.all
, or etc.) are a queue of rules that apply to incoming requests. Note that this registration happens at the server-start time and is a part of the server itself, not requests.
Once it's all set up and the server is running, any hop (step in the queue, a.k.a middleware) after the first one is called only if the previous hop has called next()
explicitly. In other words, if you put a app.use((req, res, next) => {});
at the beginning of all the middlewares, the server is gonna do absolutely nothing! -- this middleware is just swallowing any incoming request and not calling next()
.
Now the problem is, how can you register a middleware that:
Satisfying the second requirement is not easy. Because as we mentioned above the last hop in this rules queue runs only when all the previous ones have gracefully called next()
one after another. And sometimes it doesn't happen for various reasons, including simply forgetting to call next()
! And it's hard to enforce people to do that.
I need to mention what @robertklep said in a comment above bolder. It's using on-finished
on res
! https://github.com/jshttp/on-finished
Example:
// have this before all the other middlewares
app.use((req, res) => {
console.log("I'll be the first line executed, almost ever!");
onFinished(res, (err) => {
console.log("and I'll be the last one, knowing response"
+ " code which is already sent is: " + res.statusCode);
});
};
What this does is, actually listening on when the response is finished (you can alternatively use on-headers). So it's a whole new dimension of doing a job on express, prependicular to the existing middlewares queue mechanism. Just be careful and enjoy! ;)
Upvotes: 2
Reputation: 61
Finally it worked. Actually, in some routes, i forgot pass next() in the end of each router.
Now i do another method, utilizing responseTime function and it works perfectly without add next() to all every routes. Thanks all!
app.use(responseTime(function (req, res, time) {
var data = {};
var method = req.method;
if(method == 'GET'){
data = req.query;
} else {
data = req.body;
}
log.info(method, iduser, req.path, ' - ', Math.round(time), 'ms', ' : ', JSON.stringify(data));
}))
Upvotes: 0
Reputation: 1346
middleware is just a function that do something and then pass the request to the next function using "next()". So if you really want to do that you need to catch all of your routes in the same route something like this
app.all('*', (req, res) => {
// do something before
// your async code here
// do something after
});
Upvotes: 0