Pass Parameter to Function Express JS - javascript

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

Related

(Express)How to pass a value from function to another one in express.Router().get

How I can pass value from function to another one at router.get
router.get('/someurl', (req, res, next) => {
const token = req.headers.authorization.split(' ')[1] //jwtToken
const jwt = jwt.verify(
token,
jwtSecret
)
...do something to pass value to the next function
}, )
You can use res.locals to do that
An object that contains response local variables scoped to the request, and therefore available only to the view(s) rendered during that request / response cycle (if any).
So in your case
router.get(
"/someurl",
(req, res, next) => {
const token = req.headers.authorization.split(" ")[1]; //jwtToken
const jwt = jwt.verify(token, jwtSecret);
// pass to res.locals so I can get it in next() middleware
res.locals.token = token;
next();
},
(req, res, next) => {
// inside the next() middleware
// get token from res.locals
const previousToken = res.locals.token;
}
);

Use an array of middlewares at express.js

I'm trying to use an array of middlewares. Well, more like a combination of function names and arrays.
Instead of having:
router.post('/editPassword', validate, changePassword, sendConfirmation);
I would like to have something like:
router.post('/editPassword', validate, [changePassword, sendConfirmation] );
That would look like:
router.post('/editPassword', validate, doAction );
Where doAction would be an array like this:
var doAction = [
//equivalent of changePassword
function(req, res, next){
//whatever
next();
},
//equivalent to the previous sendConfirmation
function(req, res, next){
//whatever
}
]
But it seems it is failing and going back to the validate step after the next() within the first function in doAction.
I'm looking for a way to simplify the middleware chaining including some middleware steps under the same name.
Latest version of Express can handle this:
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
var logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, function (req, res, next) {
res.send('User Info')
})
You can review more from this link
I assume the reason you wanted it to look that way is not only for it to appear presentable, but also to be able to reuse the other middleware. In that case, you can create a middleware which runs all other middlewares to do the check for you, and only calls the next function if all validations succeed.
var express = require('express');
var app = express();
function middleware1(req, res, next) {
if(req.query.num >= 1) {
next();
} else {
res.json({message: "failed validation 1"});
}
}
function middleware2(req, res, next) {
if(req.query.num >= 2) {
next();
} else {
res.json({message: "failed validation 2"});
}
}
function middleware3(req, res, next) {
if(req.query.num >= 3) {
next();
} else {
res.json({message: "failed validation 3"});
}
}
function combination(req, res, next) {
middleware1(req, res, function () {
middleware2(req, res, function () {
middleware3(req, res, function () {
next();
})
})
})
}
app.get('/', combination, function (req, res) {
res.send('Passed All Validation!');
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
You can test this app by running it then viewing http://localhost:3000/?num=3, changing the value 3 to a lower number, or removing the num parameter.
I'm not sure if this is the proper way to do it, but this is how I've handled my other projects. Let me know what you think.
note: see comments for use case. #robertklep may have a better solution depending on how you want to use middlewares
Just search a little more ^^ : Less ugly and more understandable than previous answer
https://github.com/blakeembrey/compose-middleware
Be careful that you're not doing (the equivalent of) this in your validate middleware:
function middleware(req, res, next) {
if (someCondition) {
console.log('some condition is true');
next();
}
console.log('some condition is false');
res.status(400).end();
}
The intention here is that after calling next the rest of the code isn't executed, but it will. There's nothing really special about next, so when you call it, after it returns the middleware code continues to run (causing both "some condition is true" and "some condition is false" to be logged).
That's why you often see this:
if (someCondition) {
console.log('some condition is true');
return next();
// Or, alternatively:
// next();
// return;
}
The return causes the middleware function to return after calling next, so the rest of the code in the function won't be executed.
This functionality is already built into express as an array or middleware:
let combined = express.Router()
.use(
[
middleware1,
middleware2,
middleware3,
],
);
let combined = express.Router()
.use(
middleware1,
middleware2,
middleware3,
);
Full Example
"use strict";
let Http = require("http");
let Express = require("express");
let server = Express();
let app = Express.Router();
let combined = Express.Router();
combined.use(
function (req, res, next) {
console.log("huzzah!");
next();
},
function (req, res, next) {
res.json({ success: true });
}
);
function middleware0(req, res, next) {
console.log('ground zero');
next();
}
app.get("/combined", middleware0, combined);
server.use("/", app);
Http.createServer(server).listen(3000);

Node.js User Authentication

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.

Remove a field of my json in a specific case

I have an ExpressJS controller that list all my users
userCtrl.get :
get(req, res, next) {
var func = function(err, data) {
if (err) return next(err);
return res.json(data);
};
if (req.params[this.idName])
this._getById(req.params[this.idName], func);
else
this._getAll(func);
}
_getById(id, fn) {
this.ObjectClass.findById(id, fn);
}
_getAll(fn) {
this.ObjectClass.findAll(fn);
}
I'd like to call it from another road, in such a way that res.json() will filter a field of this json
Something like :
router.get ('/services/:serviceKey/authBridge/users', function(req, res, next) {
function anonJs(x) {
x.forEach(s => s.credential = null);
res.json(x);
}
res.json = anonJs;
userCtrl.get(req, res, next);
});
The problem is, with this last piece of code I end up with a recursion as I call res.json that is now defined as anonJS
You must store the reference to the old function before replacing it.
router.get ('/services/:serviceKey/authBridge/users', function(req, res, next) {
var json = res.json;
res.json = function(x) {
x.forEach(s => s.credential = null);
json(x);
}
userCtrl.get(req, res, next);
});

exit from chain of route specific middleware in express/ nodejs

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);

Categories