I'm not looking for authorization of a particular request and so I did this.If the request path matches I want to skip the auth.verifyToken middleware.How can I do this.I tried using return next() but its not working.
eventRouter.param('pin', (req, res, next, pin) => {
let path = `/event/matchpin/${pin}`;
if(req.path === path){
//do something here so that directly executes the route
}
//else it executes the auth.verifyToken middleware
next();
});
app.use('/user',auth.verifyToken,eventRouter);
next() is used to skip the middleware, you are just using it at the wrong place.
Try this code:
eventRouter.param('pin', (req, res, next, pin) => {
let path = `/event/matchpin/${pin}`;
if(req.path === path){
// Next will by pass this middleware
next();
}
//else it executes the auth.verifyToken middleware
});
app.use('/user',auth.verifyToken,eventRouter);
Related
How do I return both res and next in an express function:
const customfunction = async (req, res, next) => {
try {
// how do I set cookie and return next()?
return res.cookie('someToken', someToken, {
signed: true,
// etc...
}
);
return next();
} catch (err) {
// catch here, for example, return res.status(401).clearCookie...
}
}
An express request handler (like something you pass to app.get() or router.post() or something like that) does not pay any attention to the return value from that handler.
So, return inside such a handler is used only for flow control to stop further execution of the function.
In addition, your code has two return statements one after the other:
return res.cookie(...);
return next();
Which makes no sense because the return next() line of code will never be executed as the function has already returned on the line before.
If this is middleware and you intend for some other request handler to still have a chance to process this request, then you would want something like this:
const customfunction = async (req, res, next) => {
res.cookie('someToken', someToken);
next();
};
It doesn't appear that there's any reason for the try/catch because neither of these should throw an exception (assuming your code doesn't have a syntax error in it).
But, if you really wanted the try/catch, you could do this:
const customfunction = async (req, res, next) => {
try {
res.cookie('someToken', someToken);
next();
} catch(e) {
// make sure logs can see that this unexpected error is happening
console.log("customFunction error", e);
res.clearCookie('someToken');
res.status(500).send("Internal Error"); // probably want a more glamorous error page
}
};
I was under the impression that res.send() ends the request-response cycle, but without return in the else block, next(ex) is called which passes the response object to error handling middleware, resulting in Error: Can't set headers after they are sent.
Where is my understanding off? I am using express-async-errors to catch errors, if that's important.
router.get('/', async (req, res, next) => {
// get all staff sorted by name
const allStaff = await Staff.find().sort('name');
if (!allStaff) {
res.status(404).send('No staff');
} else {
return res.status(200).send(allStaff);
}
next(ex);
});
In your question, you mention it yourselves that the next() function passes the response object to the error handling middleware, so the the next middleware will execute even if you dont want it to i.e allstaff would be sent succesfully but then the next() function would be invoked.
What you are doing (without return in the else block):
Sending the allstaff object and hence trying to end the request response cycle , but then calling next() hence calling the next middleware which tries to mess up with what would otherwise have been a successful request response cycle.
router.get('/', async (req, res, next) => {
// get all staff sorted by name
const allStaff = await Staff.find().sort('name');
if (!allStaff) {
res.status(404).send('No staff');
} else {
res.status(200).send(allStaff); //send the response..expect the req-res cycle to end
}
next(ex); //then call next which might try to hamper the outgoing response
});
What you should do instead:
If you send the response then in no way should it encounter other statement which tries to send the response again, I prefer the folloing code personally:
router.get('/', (req, res, next) => {
// get all staff sorted by name
Staff.find().sort('name').exec(function (err, docs) { //this callback function will handle results
if (err) {
next(); //if there is an error..then the next middleware will end the req response cycle
} else {
if (docs.length == 0) {
res.status(404).send('No staff'); //send response,the req- res cycle ends,never disturbed again...story finished
} else {
res.status(200).send(docs); //send response,the req- res cycle ends,never disturbed again.....story finished
}
}
});
});
My question is exactly this one. The problem is that when I apply the solution to that question, nothing happens - the value of res.send isn't logged. I use express 4.16.4.
Here's my code:
/* FILE: /app.js: */
...
const postRoute = require('./middleware/postRoute');
const myRoute = require('./routes/myRoute');
...
app.use('/', myRoute);
app.use(postRoute);
...
/* FILE: /routes/myRoute */
...
router.post('/myRoute', [], (req, res, next) => {
res.send({ status:'success', message:'Test success. Feels good, man.' });
next();
});
...
/* FILE: /middleware/postRoute */
const postRoute = function(req, res, next) {
console.log('postRoute: ');
var send = res.send;
res.send = function(chunk, encoding){
res.send = send;
if (chunk) {
console.log('postRoute chunk: ', chunk); // This statement is never reached
}
res.send(chunk, encoding);
};
next();
};
module.exports = { postRoute };
When I make a POST request to /myRoute using Postman, it logs the following: postRoute:, and that's it. The second console.log() is never reached and presumably neither is any other statement in the same function() as the console.log().
The question I link to at the start of my question was from 2015, when I assume they used a different version of Express.js, and that's why their solution isn't working for me? In my middleware code example, I used the code from a question that was linked in one of that question's answers, because it's solution didn't work for me. But that solution's obviously also not working, otherwise I wouldn't be here - and it's from 2012! Who even knows what version of Express they used back then!?
So to reiterate and conclude my question: How do I use middleware to log the value passed to res.send()?
Follow up question (but let me know if I should rather ask this in a separate question): Is there a way to call middleware after the route/response from the route instead of globally. So router.post('/myRoute', [postRoute], (req, res, next) => {...}); instead of app.use(postRoute)?
Here's what I ended up doing. I kept my file structure exactly the same, but instead of res.send()ing from the route, I attached the object that I would have sent, to the res object and then call next() at the end of my route. So for instance, res.send({message:'blah'}); becomes res.return = {message:'blah'}; next();. I use .return because I don't believe such a property exists on the res object by default and I find it descriptive enough for my purposes. Then in my postRoute middleware, I can easily access res.return, after which I call return res.send(res.return).
Using my example from the question (app.js stays exactly as you see it):
/* FILE: /routes/myRoute */
...
router.post('/myRoute', [], (req, res, next) => {
if(theConditionIsMet()) {
res.return = { message:'The condition was met.' };
} else {
res.return = { message:'The condition was not met.' };
}
next();
});
....
router.post('/anotherRoute', [], (req, res, next) => {
// In this route I don't need to intercept the response, so I just do it like normal.
return res.send({ message:'Feels good, man.' });
});
...
/* FILE: /middleware/postRoute */
const postRoute = function(req, res, next) {
if(res.hasOwnProperty('return') {
return res.send(res.return);
}
};
module.exports = { postRoute };
One flaw I can already see is that I'll now have to restructure all my routes to use this method of res.send()ing (or at least all of the routes for which I want to intercept the return value). Because of this, and because I imagine someone more knowledgeable than me could probably figure out a better way to do it, I'm not going to accept my own answer.
Anyone help me..I am new in nodejs ..how to call one route inside another route.doing some query in getmsg route and result of the first one calling text route deletemsg..
app.post('/getmsg', function (req, res) {
app.post('/deletemsg',{id:2});//need to call this
}
app.post('/deletemsg', function (req, res) { //do something
}
A simple solution, put a function in the route /deletemsg
app.post('/getmsg', function (req, res) {
getCalled(req,res,{id:2});//pass req, res and the object you want to send
}
app.post('/deletemsg',getCalled) // pass function here
function getCalled(req, res, obj) {
//do something
}
i think this is not a gud trick if you want to delete column with app.post
you need to send id with body object the get look like this
$http.post('/getmsg',{id:2})
.success(function(success){
//do someting with success response
})
.error(function(err){
//do somthing with err response
})
and server should be like this (as NoDownvotesPlz suggests):
app.post('/getmsg', function (req, res) {
var id = req.body.id;
getCalled(req,res,id);//pass req, res and the object you want to send
}
app.post('/deletemsg',getCalled) // pass function here
function getCalled(req, res, obj) {
//do something
}
Take the following POST function in express. (I am using express 3.5.1)
app.post('/example', someFunctionOne, someFunctionTwo, function(req, res){
if(!req.someVar){
return res.send(400, { message: 'error'});
} else{
return res.json(200, { message: 'ok'});
}
});
If I get some result from someFunctionOne which means someFunctionTwo is redundant, is there a way to skip someFunctionTwo and go to the last unnamed function which will send the response?
So I guess in the same way there is the "next()" function where is the "last()" function? If this is not possible why not? It seems like an oversight to me but is there a good reason?
You can do next('route') which will go to the next route entirely. This is not exactly what you need in this case, but it would work if you broke your code up into 2 separate routes.
However, I think there are generally 2 approaches to this kind of conditional logic:
make someFunctionOne put some state on the req instance when it gets the special result and make someFunctionTwo smart enough to check for that and when found call next() and bypass itself. This is the most idiomatic express thing to do, and it's how most middleware detect when they have been called more than once on the same request and avoid redoing their work again.
In someFunctionOne, when the special case happens, just invoke lastFunction directly. Remember the middleware abstraction isn't the holy grail. If your middleware are so tightly coupled, maybe they should be one middleware and some helper functions. There are lots of other ways to organize code that might feel more natural.
My instinct is to do something like this:
const funcOne = (req, res, next) => {
// do something
if (/* you were successful */) {
res.locals.shouldSkipFuncTwo = true
}
next()
}
const funcTwo = (req, res, next) => {
if (res.locals.shouldSkipFuncTwo) return next()
// do whatever stuff
next()
}
router.get('/', funcOne, funcTwo, (req, res) => {
res.status(200).send('hello world')
)}
If you haven't used res.locals before, here are the express docs on it. Basically, it's a property in the response object that's there for you to use as a container.
Probably the best way to do it to make some helper or put your own middleware into chain instead of your functions.
So your code will look like:
app.post('/example', oneOf(key, someFunctionOne, someFunctionTwo), function(req, res){
if(!req[key]){
return res.send(400, { message: 'error'});
} else{
return res.json(200, { message: 'ok'});
}
});
And the helper should be something like that:
function oneOf (key) {
var fns = Array.prototype.slice.call(arguments, 1);
var l = fns.length;
return function (req, res, next) {
var i = 0;
function _next () {
if (req[key] || i === l) return next();
fns[i](req, res, _next);
i += 1;
}
_next();
}
}
If you will decide to do it just here the code will looks like:
app.post('/example', functionOneOrTwo, function(req, res){
if(!req.someVar){
return res.send(400, { message: 'error'});
} else{
return res.json(200, { message: 'ok'});
}
});
function functionOneOrTwo(req, res, next) {
someFunctionOne(req, res, function () {
if (req.someVar) return next();
someFunctionTwo(req, res, next);
});
}
Simple, but untested ;-)
Actually I was facing the very same problem. And I just found the express-unless module which does exactly this: https://github.com/jfromaniello/express-unless