I'm practicing with simple .get methods in node/express. I'm following an example of a book, but I have no session variable and i have no templates; so i've commented that lines and i've replaced them with a simple .send method, and i've replaced with a simple hardcode variable: authorized.
I'm getting the error: ReferenceError: res is not defined
The problem is that I have no res variable, because the control pass first on authorize function.
function authorize(req, res, next){
authorized = true;
// if(req.session.authorized) return next();
if(authorized) return next();
res.send('not-authorized');
}
app.get('/secret', authorize, function(){
// res.render('secret');
res.send('secret');
});
app.get('/sub-rosa', authorize, function(){
// res.render('sub-rosa');
res.send('sub-rosa');
});
thanks to comments, the solution is:
function authorize(req, res, next){
authorized = true;
// if(req.session.authorized) return next();
if(authorized) return next();
res.send('not-authorized');
}
app.get('/secret', authorize, function( req, res ){
// res.render('secret');
res.send('secret');
});
app.get('/sub-rosa', authorize, function( req, res ){
// res.render('sub-rosa');
res.send('sub-rosa');
});
Related
everything good ? I would like to know the best way and if it is possible to send a certain parameter to an express function in the NodeJS.
i wanna pass the string ('admin') or other string that i want to function 'RoleTolen', using my route.
function verifyToken
function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers["authorization"];
// Check if bearer is undefined
if (typeof bearerHeader !== "undefined") {
// Split at the space
const bearer = bearerHeader.split(" ");
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
} else {
// Forbidden
res.sendStatus(403);
}
}
function ValidToken
function validToken(req, res, next) {
jwt.verify(req.token, process.env.SECRET, (err, authData) => {
if (err) {
res.sendStatus(403);
} else {
next();
}
});
}
function RolesToken
function rolesToken(role, req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
}
my route
router.post(
"/posts",
verifyToken,
validToken,
rolesToken("admin"),
customerController.posts
);
function rolesToken(role, req, res, next) is not a proper Express.js route handler, as you already know (and hence the question, I assume).
What you can do is to write your rolesToken as a function that returns the actual Express.js compliant handler (function):
function rolesToken(role) {
return function(req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
};
}
from the docs
Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature (err, req, res, next)):
Therefore your RolesTaken function won't work as expected.
Secondly, you can create a middleware or modify existing one
(req, res, next) => {
//some stuff
if(req.path == '/posts') req.role= 'admin';
if(req.path == '/someOtherPath') req.role= 'someRole';
//some other stuff
}
Now you can get the get the role in req.someProp in the your controller middlerware as req.role
you would like to see this question also
I'm currently trying to redirect to an external site with node and express specifically in a get call. However, I can't seem to find a possible solution. Any help would be appreciated. Note that when trying response.redirect I'm getting TypeError: res.redirect is not a function. However, when I view the express documentation it seems to be in there.
app.get('/:urlToForward', (res, req, next)=>{
//Stores the value of param
// var shorterUrl = res.params.urlToForward;
// shortUrl.findOne({'shorterUrl': shorterUrl}, (err,data)=>{
// // if (err) {
// // res.send("This shorterUurl does not exist.");
// // }
// // else {
// // res.redirect(301, data.originalUrl);
// // }
// // response.end();
// });
res.redirect('https://www.google.com');
});
Order matters in the arguments. req must be first, then res, then next.
app.get('/:urlToForward', (req, res, next)=>{ ...
You can do res.redirect('http://app.example.io');
Express docs: http://expressjs.com/api.html#res.redirect
Just use simple:
app is instance of invoked Express application.
app.get('/', function(request,respond) {
respond.redirect('your_url'); //Pass between the brackets your URL.
});
Note you can use ES6 shorthand for shorterUrl, no need to type it out twice.
app.get('/:urlToForward', (req, res, next)=> {
//Stores the value of param
var shorterUrl = res.params.urlToForward;
shortUrl.findOne({shorterUrl}, (err, data)=> {
if (err) {
res.send("This shorterUrl does not exist.");
}
else {
res.redirect(data.originalUrl);
}
response.end();
})
});
I'm new with nodeJs and i'm actually following a tutorial about it.
In the tutorial, a code was used:
In a verify.js file the following function was written:
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
and in another file, the function was called so :
/*****........****/
.post(verify.verifyOrdinaryUser, function(req, res, next){
/******.......*****/
everything is working fine without problem.
1- I don't understand why the function verify.verifyOrdinaryUser is not called so :
verify.verifyOrdinaryUser(req, res, next)
with his parameter (how is it possible that we call a function without his parameter .?
next , i've written a function :
exports.verifyAdmin = function(req, res, next){
if(req.decoded._doc.admin == false){
var err = new Error('You cannot access to this ressource!');
err.status = 401;
return next(err);
}
else {
next();
}
};
in the same file, to verify if a user is a admin or not, i have to call this function after the verifyOrdinaryUser function,
my problem is i don't know how i can make call of this function, with or without the parameters.
Thank you.
1- I don't understand why the function verify.verifyOrdinaryUser is
not called so : verify.verifyOrdinaryUser(req, res, next)
In simplest terms, That's because Express takes care of sending those parameters to the specified middleware instead of you specifying it here
And in function verify.verifyOrdinaryUser, The function is requesting for 3 parameters req, res, next and it receives those three parameters, if it requests for a parameter that doesn't exist, That parameters value will be undefined.
my problem is i don't know how i can make call of this function, with
or without the parameters.
Just call it like
/*****........****/
.post(verify.verifyOrdinaryUser, verify.verifyAdmin, function(req, res, next){
/******.......*****/
And in the functions code you can request for the parameters you need
exports.verifyAdmin = function(req, res){
if(req.decoded._doc.admin == false){
...
Hope this gives you some sense on whats going on, You should google for Node JS Middlewares and simple tutorials based on Node JS and Express.
My code looks something like this:
router.route('/user')
.post(function(req, res, next){
queryDB(arg1, arg2, prepareRes)
})
.get(function(req, res, next){
queryDB(arg3, arg4, prepareRes)
});
var prepareRes = function(err, data){
if(err) next(err);
else{
req.data = data;
}
};
when i run this code i get the following error:
ReferenceError: next is not defined
or
ReferenceError: req is not defined
This happens because req and next ,are outside prepareRes scope.
How can get around this ERROR??
I don't want to have to duplicate the same lines of code in both routes and its not possible to use
route.all
in my case.
prepareRes is declared outside of the post and get handlers so it has no access to the req(uest) or next.
The most obvious solution is to add request and next parameters to the prepareRes function signature and then, when calling prepareRes in the request handlers, to wrap the call in an anonymous function that can access them:
router.route('/user')
.post(function(req, res, next){
queryDB(arg1, arg2, function(err, data){
prepareRes(err,data, req, next);
})
})
.get(function(req, res, next){
queryDB(arg3, arg4, function(err, data){
prepareRes(err,data, req, next);
})
});
var prepareRes = function(err, data, req, next){
if(err) next(err);
else{
req.data = data;
}
};
Using something like lodash you you could get rid of the anonymous functions and partially apply the additional arguments like so:
queryDB(arg1, arg2, _.partialRight(prepareRes, res, next));
But you still have to change the prepareRes signature.
since prepareRes is not inside of any of the above functions, where req,res are provided it can not find req on its namespace, assuming req and next are not globals.
Here for instance: req and next are passed to an error handler function:
function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something blew up!' });
} else {
next(err);
}
}
Then next and res is available in the scope.
I have a chain of "route specific middleware" for this route, like so:
var express = require('express');
var server = express();
var mw1 = function(req, resp, next) {
//do stuff
if (success) {
next();
} else {
req.connection.destroy(); //without calling next()
}
};
var mw2 = function(req, resp, next) {
//do stuff
if (success) {
next();
} else {
req.connection.destroy(); //without calling next()
}
};
server.post('/some/path', [mw1, mw2], function(req, resp) {
//write response
});
[mw1, mw2] are the middleware specific to the route /some/path.
This is different from server-wide middleware like this:
server.use(mw1);
server.use(mw2);
Where it applies to all routes defined.
Now my issue is that I want to exit from the chain. I.e. if success is false in mw1, I do not wish for mw2 to be called. If success is false in mw2, I do not without for the route function to be called. Presently, both mw1 and mw2 appear to be getting called whether or not next() is called - and I do not know why.
How can I go about doing this?
You can call next( 'route' ), as said on the express api reference, application routing section:
Multiple callbacks may be given, all are treated equally, and behave
just like middleware, with the one exception that these callbacks may
invoke next('route') to bypass the remaining route callback(s).
Example
var express = require('express')
, app = express()
;
// keep an eye on the function names
app.post( '/some/path', middleware1, middleware2, function route1( req, res, next ) {
// write response
});
app.all( '*', function route2( req, res, next ) {
// do something like handle a 404 request
});
app.use(function errorHandler( err, req, res, next ) {
// handle error
});
function middleware1( req, res, next ) {
// ...
if ( !success ) {
// bypasses middleware2 and route1, route2 will be called
return next( 'route' );
}
// calls middleware2
next();
}
// intentionally similar to middleware1 to keep things clear
function middleware2( req, res, next ) {
if ( !success ) {
// bypasses route1 and route2
// errorHandler will be called with the error
return next( Error( 'middleware 2 failed' ) );
}
// calls route1
next();
}
A little more tinkering yielded the answer:
var express = require('express');
var server = express();
var mw1 = function(req, resp, next) {
//do stuff
if (success) {
next();
} else {
resp.send(406, 'Invalid because of this');
req.connection.destroy(); //without calling next()
}
};
var mw2 = function(req, resp, next) {
//do stuff
if (success) {
next();
} else {
resp.send(406, 'Invalid because of that');
req.connection.destroy(); //without calling next()
}
};
server.post('/some/path', [mw1, mw2], function(req, resp) {
//write response
});
The trick was send a response: resp.send(406, 'Invalid because of this');
Just prior to destroying the connection: req.connection.destroy();
In fact not destroying the connection, I found to also work, in the general case.
(But was required in my specific case, and is out of the scope of this question.)
If the response has already been sent, then express does not automatically call next() for you, as it appeared to do otherwise.
I was under the impression that if you neither call next() nor send a response in a route handling function, express just hangs. Also FWIW I haven't used an array, mine looks like server.post('/some/path', mw1, mw2, function(req, resp) {...
Anyway. One alternative might be to restructure your code so you only have a single handling function. Do you have a good reason for mw1 and mw2 being middleware instead of regular async functions your handler calls?
var express = require('express');
var server = express();
var mw1 = function(req, res, callback) {
// do stuff with req/res if necessary but don't send a response
if (success) {
callback(null);
} else {
callback('Error');
}
};
var mw2 = function(req, res, callback) {
//do other stuff but don't send a response
if (success) {
callback(null);
} else {
callback('Error');
}
};
function mwBoth(req, res){
mw1(req, res, function(err){
if(err){ return res.send(500) };
mw2(req, res, function(err){
if(err){ return res.send(500) };
// neither had an error
res.redirect('/some/other/path');
});
});
};
server.post('/some/path', mwBoth);