A middleware containing res.locals is not working - node.js

Hi I am using this given middleware to show username userid etc on every template but this middleware is not working neither console.log working nor locals working in my ejs template. Please check why!
I am using this middleware in the last before app.listen.
app.use(function(req, res, next) {
console.log("Hello");
res.locals.username = req.session.username;
res.locals.userid = req.session.userid;
res.locals.w_id = req.session.w_id;
next();
});

I am using this middleware in the last before app.listen.
That's your issue, you must add this middleware before all the routes so that it will be called.

Related

add middleware to all routes but a few

how can I add middleware to all possible routes except for these that match a given expression?
I know how to add a middleware to ones that match an expression:
app.all('/test/*', requireLogin);
but I want to require login in all routes except for a few that have a specific prefix in their paths.
If you are using express 3.x series you are out of luck here. You need to hack the middle ware to to check the the path.
app.use(function(err, req, res, next){
if(canRouteSkipLogin(req.path)
next();
else{
//Do the auth logic
}
});
canRouteSkipLogin = function(path){
//logic to find the path which can skip login
}
While in express 4.0 you can do it much easier way.
var authRoutes = express.Router();
var nonAuthRoutes = express.Router();
authRoutes.use(function(req, res, next) {
//Do Auth Logic here
});
Hope this explains.
The only way I've been able to do this is to just explicitly code for it with a guard clause in the middleware itself. So the middleware always gets called, it checks req.path against the bypass regex, and if so, just calls next() immediately and returns. This is the pattern used by things like the expressjs body-parser (via the type-is module) to no-op themselves based on checking that a given request doesn't require them to do anything.

Using Express 4 how to redirect to my own route without losing req and response data?

I have my application structured with 3 Routes (api, admin, default). Each lives in there own file and has it's own middleware and exports a Route. The problem I am facing is when I want to forward to another route that lives on a different router. Essentially I want to call the same function so that I am not serving up the same view from multiple locations.
I don't want to user res.redirect('/someplace') because I want to be able to pass the req and res objects on to the method.
|-app.js
|-routes
|---admin.js
|---api.js
|---default.js
The routes are required and used in app.js as follows
app.use('/api', require('./routes/api')(passport);
app.use('/admin', require('./routes/admin')(passport);
app.use('/', require('./routes/default')(passport);
Inside of admin if have a situation where I need redirect to login and pass some data
// authenticates all routes for the admin router
router.use(function(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.flashMessage.push('Session expired'); //is lost after redirect
res.redirect('/login');
//do I need to restructure my whole app so that I don't
//have to call res.redirect('login')
});
Any ideas on how to structure this? Do I need to export every method and keep all of my routes in one router file? That doesn't very clean, but if the functions are somewhere else it may be too messy.
You can forward it by calling the next callback ,but only if you do not use any paths.
app.use(function(req, res, next) {
// ... api
next();
});
app.use(function(req, res, next) {
// ... admin
next();
});
Another option is use * that will match all paths:
app.use("*", function(req, res, next) {
var path = req.path; // just example how it can be done
if (path === "/api") {
// ...
path = "/admin";
}
if (path === "/admin") {
// ...
}
});
Edit:
I don't think that express has something like next('/login'); ,so basically function that can forward a request to another path and I don't think that is right to have something like this. If a client ask for /admin you should send this particular page and not the page that is under /login. If you want to send back to a client the login page than just redirect it as you did it in your question. I understand that you want to keep the req, res ,but then is the problem in the proposal/structure of your webapp.

Node.js matching the url pattern

I need an equivalent of following express.js code in simple node.js that I can use in middleware. I need to place some checks depending on the url and want to do it in a custom middleware.
app.get "/api/users/:username", (req,res) ->
req.params.username
I have the following code so far,
app.use (req,res,next)->
if url.parse(req.url,true).pathname is '/api/users/:username' #this wont be true as in the link there will be a actual username not ":username"
#my custom check that I want to apply
A trick would be to use this:
app.all '/api/users/:username', (req, res, next) ->
// your custom code here
next();
// followed by any other routes with the same patterns
app.get '/api/users/:username', (req,res) ->
...
If you only want to match GET requests, use app.get instead of app.all.
Or, if you only want to use the middleware on certain specific routes, you can use this (in JS this time):
var mySpecialMiddleware = function(req, res, next) {
// your check
next();
};
app.get('/api/users/:username', mySpecialMiddleware, function(req, res) {
...
});
EDIT another solution:
var mySpecialRoute = new express.Route('', '/api/users/:username');
app.use(function(req, res, next) {
if (mySpecialRoute.match(req.path)) {
// request matches your special route pattern
}
next();
});
But I don't see how this beats using app.all() as 'middleware'.
You can use node-js url-pattern module.
Make pattern:
var pattern = new UrlPattern('/stack/post(/:postId)');
Match pattern against url path:
pattern.match('/stack/post/22'); //{postId:'22'}
pattern.match('/stack/post/abc'); //{postId:'abc'}
pattern.match('/stack/post'); //{}
pattern.match('/stack/stack'); //null
For more information, see: https://www.npmjs.com/package/url-pattern
Just use the request and response objects as you would in a route handler for middleware, except call next() if you actually want the request to continue in the middleware stack.
app.use(function(req, res, next) {
if (req.path === '/path') {
// pass the request to routes
return next();
}
// you can redirect the request
res.redirect('/other/page');
// or change the route handler
req.url = '/new/path';
req.originalUrl // this stays the same even if URL is changed
});

Node.js pass variable to route

I have very simple node.js noob question. How do I pass a variable to an exported route function?
Routes file
exports.gettop = function(n, req, res) {
console.log(n);
res.send(200);
};
Server file
app.get('/api/v1/top100', routes.gettop(100));
Error: .get() requires callback functions but got a [object Undefined]
For your example, you want to create a new function that will close around your value of n. In your case, you are executing gettop and passing the returned value to express as your route, which means gettop needs to return the route handler.
exports.gettop = function(n){
return function(req, res) {
console.log(n);
res.send(200);
};
};
As your code looks like you're using express you can use express app locals and express result locals to pass variables to your route. While the other answers propose working solutions I think that it's less obtrusive to use express mechanisms to set these variables.
With response locals (See Express API reference) you first have to set a variable somewhere in a middleware or route. I'll show the middleware approach
app.use(function(req,res, next) {
res.locals.top = 200;
next();
});
then in your route you can access this property via res.locals.variablename
exports.gettop = function(req, res) {
console.log(res.locals.top);
res.send(200);
};
In case you want to make these settings application wide a better approach is to use app locals (See Express API reference)
To set an app locals variable you can use
app.locals.top = 100;
To access this variable from your route use
exports.gettop = function(req, res){
console.log(req.app.locals.top);
res.send(200);
};
As an alternative to loganfsmyth's (very valid!) solution, you could leave your gettop function as-is and create a partial function:
app.get('/api/v1/top100', routes.gettop.bind(null, 100));
Try
app.post('/find_user',
require('./naas/autentication'),
require('./naas/authorization')(paramForRouter),
require('./routes/users'));
Where
require('./naas/autentication') is for example
module.exports = function (req, res, next) {next();}
And require('./naas/authorization')(paramForRouter) is
module.exports = function (paramForRouter) {
return function (req, res, next) {
this.param = paramForRouter;
console.log("Param value",this.param);
next();
};
};

Node.js Express3 - Middleware to add render data to all render requests

Is it possible through express middleware or another method to add render data (the second option in res.render) to each call in the apps routes.
My app is using passport for authentication and I would like a middleware to always append the user information to each rendered template.
Currently each of my calls to res.render look similar to. I would like to remove the user : req.user and add that to a middleware function.
// Page 1
res.render("somepage1",{data : "somepage1", user : req.user});
// Page 2
res.render("somepage2",{data : "somepage2", user : req.user});
Express does provide app.locals and res.locals, which it automatically merges with explicit locals passed in to render by a route handler.
app.use(function(req, res, next) {
res.locals.user = req.user;
next();
});
Alternatively, you could hot patch the render function. I'd avoid this since it's extra overhead, but if for some reason you needed to pass information not available before your route handler runs, it's an option:
app.use(function(req, res, next) {
var render = res.render;
res.render = function(view, locals, cb) {
if (typeof locals == 'object') locals.user = req.user;
render.call(res, view, locals, cb);
};
next();
});
Figured it out.
You can use locals in your middleware.
app.use(function(req, res, next){
res.locals.user = req.user;
next();
});
Then in the templates use.
<h1>User Name:{{user.name}}</h1>
<h1>User Name:{{_locals.user.name}}</h1>

Resources