I am trying to handle simple user information through cookies, this information is visible in my layout through res.render, but I saw it very tedious, since it will always be simple information and I would have to be doing it in each .get (), then in app.js I did this:
app.js
app.use(function(req,res, next){
var cookies = req.cookies;
if(!cookies.UserData){
console.log('cookies no exists');
}
else{
console.log('cookies');
res.locals.user = cookies.UserData;
next();
}
});
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
layout.ejs
<%- user.username %>
but "user" was not defined, but in my error.ejs When a 404 was generated, I put "<%- user.username %>" it in and it worked.
but it only works on 404 catches and not in general, what am I doing wrong? how I do this?
how I solved it
In my Router-level middleware:
var express = require('express');
var router = express.Router();
router.use(function(req,res, next){
var cookies = req.cookies;
if(!cookies.UserData){
console.log('cookies no exist');
}
else{
console.log('cookies');
res.locals.user = cookies.UserData;
next();
}
});
I put it first in the router-level middleware, above all the other http methods
Related
1.Can anyone tell me how to allow my error to pass through the app.use('/blogs','blogRoutes') middle ware that scopes my url to a api file?
2.Is the answer something like app.use('/blogs','blogRoutes', next){next(err)}?
const express = require('express');
const morgan = require('morgan');
//use Mongo Db
const mongoose = require('mongoose');
const blogRoutes = require ('./route/blogroutes');
const app = express();
//connect to mongo db
const dBurI = mongo database key
mongoose.connect(dBurI, {useNewUrlParser: true, useUnifiedTopology: true});
.then((result)=> app.listen(3000))
.catch((err)=>console.log(err))
//middleware stack
// allows use of view engine to render - html files in views foles are suffixed with ejs these are found automatically due to views folder beign recognised
app.set('view engine','ejs');
app.use(express.static('public')); //access ppblic folder files - css
app.use(express.urlencoded({extended: true})); //url data and passes into object that can be used on req => req.body
app.use(morgan('dev'));
//redirect route
app.get('/',(req, res, next)=>{
res.redirect('/blogs');
next(err);
});
app.get('/about',(req, res, next)=>{
//send file to a browser
res.render('about', {title: 'About' });
next(err);
});
//redirect 301
app.get('about-me',(req,res, next)=>{
res.redirect('./about');
next(err);
});
//blogroutes
app.use('/blogs','blogRoutes'); //scope all blog urls to blogrouter
// middle ware app.use is called immediately if above are not found - error page 404
app.use((err,req,res)=>{
res.status(404).render('404', {title: '404', error: err });
});
1.after reading the express documentation I believe the answer for espress5+ is as follows:
//redirect route
app.get('/',(req, res, next)=>{
res.redirect('/blogs');
});
app.get('/about',(req, res, next)=>{
//send file to a browser
res.render('about', {title: 'About' });
});
//redirect 301
app.get('about-me',(req,res, next)=>{
res.redirect('./about');
;
});
//blogroutes
app.use('/blogs','blogRoutes',(req,res,next)); //scope all blog urls to blogrouter
// middle ware app.use is called immediately if above are not found - error page 404
app.use((err,req,res, next)=>{
res.status(404).render('404', {title: '404', error: err });
});
2.read this doucmentations and see if im write if not then I believe I have to do this:
//redirect route
app.get('/',(req, res, next)=>{
res.redirect('/blogs');
next(err);
});
app.get('/about',(req, res, next)=>{
//send file to a browser
res.render('about', {title: 'About' });
next(err);
});
//redirect 301
app.get('about-me',(req,res, next)=>{
res.redirect('./about');
next(err);
});
//blogroutes
app.use('/blogs','blogRoutes',(req,res,next)=>{next(err);}); //scope all blog urls to blogrouter
// middle ware app.use is called immediately if above are not found - error page 404
app.use((err,req,res, next)=>{
res.status(404).render('404', {title: '404', error: err });//next would call the express error handler automatically if used here..
});
Following is the error handling behaviour in Express - 4.17:
You do not need to explicitly pass the error to the error handling middleware for synchronized operation. Express will take care of it for you. This can be confirmed by sending a GET request to the / route. In this case, your app does not crash.
If an error occurs during async operations, you must explicitly pass the error to the next middleware using next(). I created two routes to test this behaviour: /async and /async_next. If you visit the /async route, your app should crash because we are not explicitly handling the error. Once you restart your app and navigate to the /async_next route, you will notice that it does not crash and that the error is handled by the custom error handling middleware.
For understanding the above points refer to the following code -
const express = require('express');
const app = express();
app.listen('3001', () => console.log("listening port - 3001"));
app.get('/async', (req, res, next) => {
console.log('Async function');
setTimeout(() => { throw new Error('Async Err from settimeout') }, 1);
})
app.get('/async_next', (req, res, next) => {
console.log('Async function');
setTimeout(() => {
next(new Error('Async Err from settimeout'))
}, 1);
})
app.get('/', (req, res, next) => {
throw new Error('Random Sync Err');
});
app.use((err, req, res, next) => {
console.log('Error from custom handler ', err);
res.send('Error');
});
1.so this seems right but need testing...
//redirect route
app.get('/',(req, res, next)=>{
res.redirect('/blogs');
});
app.get('/about',(req, res, next)=>{
//send file to a browser
res.render('about', {title: 'About' });
});
//redirect 301
app.get('about-me',(req,res,next)=>{
res.redirect('./about');
});
//blogroutes
app.use('/blogs','blogRoutes',(req,res,next)); //scope all blog urls to blogrouter
// middle ware app.use is called immediately if above are not found - error page 404
app.use((err,req,res,next)=>{
res.status(err.status).render('404', {title: 'Error Page', error_message: 'err.message'});
}):
You error handler needs to look like this even with express 5+
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
You need the err argument to reference to the error...
i come to you because i'm stuck for rewrite my url in javascript.
For example when user make a request for deposit page , my url looks like '/member/deposit' but i just want '/deposit'. i'm using a MVC architecture.
index.js // Where i define all routes file
const
homeRoute = require('./home'),
memberRoute = require('./member');
function init(server) {
server.get('*', function (req, res, next) {
res.locals.user = req.user || null;
return next();
});
server.use('/', homeRoute);
server.use('/member', memberRoute);
}
module.exports = {
init: init
};
router member.js // Where i define all member routes
const
express = require('express'),
memberController = require('../controllers/member');
let router = express.Router();
router.get('/*', function(req, res, next){
if (req.session.user && (req.session.user.role == "member"))
next();
else
res.redirect('/login');
});
router.get('/', memberController.deposit);
router.get('/deposit', memberController.deposit);
router.get('/withdraw', memberController.withdraw);
module.exports = router;
controller member.js // where all code is executed before rendering
function deposit(req,res){
res.render('member/deposit',{
title:'Deposit'
});
}
function withdraw(req,res){
res.render('member/withdraw',{
title:'Withdraw'
});
}
Any help would be appreciated, i've not find response on stackoverflow
It can be use this way:
server.use('/', homeRoute);
server.use('/', memberRoute);
As long as the link in homeRoute and memberRoute have no duplication.
Or
The complete rewrite of url can be done as in the following link:
https://gist.github.com/ramonfritsch/06893c1c561d670687a9aee3bbc4e9c7
when dealing with routes, I want to check if the route is valid. If not, I always want to redirect to a notFound page.
If the user is not authorized I always want to redirect to the login page.
Otherwise I want to use the valid routes.
In my app.js I require my router.js and pass in the app as a parameter
require('./server/router')(app);
So my router works fine when having
module.exports = function(app){
app.use('/route1', require('./routes/route1'));
app.use('/route2', require('./routes/route2'));
app.use('/route3', require('./routes/route3'));
};
in there. When using this structure
module.exports = function(){
var router = require('express').Router();
router.use('/route1', require('./routes/route1'));
};
it results in
Cannot GET /route1
All my routes contain this base structure
var router = require('express').Router();
// -- Route --
router.get('/', function (req, res) { // Render the HTML here
res.render('route1', {
});
});
// -- Ajax POST --
router.post('/doSomething', function (req, res) { // Load some data
res.send({});
});
module.exports = router;
Is it not possible to use the router when it comes to require the routes?
Further I want to implement the check for invalid routes or authorized users.
app.use(function(req, res, next) {
if(!req.route){
res.redirect('/notFound'); // invalid route
} else {
var session = req.session;
if (session.user == null){ // unauthorized user
res.redirect('/login');
} else {
// valid routes here
}
}
});
How can I connect this pseudo code with my valid routes?
put at the end of your express app.js
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
if(err.status == 404) res.redirect('/notFound')
// can handle more conditions (like 500) also
})
You have to create a middleware for checking authorized users on top of all routes, and another to handle not found routes at the end:
handle unauthorized users:
app.use(function(req, res, next) {
if (!req.session.user) {
return res.redirect('/login');
}
next();
});
catch not found routes:
app.use(function(req, res, next) {
res.status(404).send('Page Not Found');
});
You may want to render error view by using res.render('error', {code: 404, msg: 'Page Not Found'});
This question already has an answer here:
Nodejs handle unsupported URLs and request types
(1 answer)
Closed 5 years ago.
var express = require('express');
var path = require('path');
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
I confused when catch 404 error and when not?
I want achieve the goal when input correct request path will not catch 404 error,otherwise bad request path will.
In your routes folder(if you are using express-gen) or anywhere else create a node module which uses express.router() as follows
var express = require('express');
var bodyParser = require('body-parser');
var dishRouter = express.Router();
dishRouter.use(bodyParser.json());
Then handle your requests, example:
dishRouter.route('/')
.get(function(req, res, next) {
res.end('Will send all the dishes to you!');
})
.post(function(req, res, next) {
res.end('Will add the dish: ' + req.body.name + ' with details: ' + req.body.description);
});
And use this in ur app.js or the main file which you run:
var express = require('express');
var path = require('path');
var dishRouter=require('./routes/dishRouter');
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use('/dishes',dishRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
res.redirect('/fail');
next(err);
});
So what this will do is that, it will handle the get and post requests from client for URI /dishes and for others, it will throw an error 404 and send to /fail path.
Remember the express use() is executed for all request, so what is happening is your 404 status is attached to all request within your application. Use it in the callback which checks whether the input is correct or not, for example if its an HTTP express post request:
// This is just an example, please note
app.post('/signin', function(req, res) {
if(!user.passwordCheck(req.body.password) {
res.status(404).send({
message: 'Incorrect input'
});
} else res.redirect('/success');
}
I hope this helps.
I´m facing a confusion issue while implementing the authentication for my restful api using passport local strategy.
Note:
I got the authentication working successfully when I´m doing it all in my index.js. But I want to use in Classes for better Code separation.
I have a passport.js Module
// config/passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var mysql = require('mysql');
var dbconfig = require('./database');
var connection = mysql.createConnection(dbconfig.connection);
module.exports = function(passport) {
// passport needs ability to serialize and unserialize users out of session
passport.serializeUser(function (user, done) {
//console.log("SER");
console.log(user),
done(null, user);
});
passport.deserializeUser(function (user, done) {
console.log("XXXX");
console.log(user);
connection.query("SELECT * FROM users WHERE name = ? ",user.name, function(err, rows){
console.log("DER");
console.log(rows);
done(err, rows[0]);
});
});
// passport local strategy for local-login, local refers to this app
passport.use('local-login', new LocalStrategy(
function (username, password, done) {
console.log("hhh");
console.log(username);
connection.query("SELECT * FROM users WHERE name = ? ",username, function(err, rows){
console.log(rows);
return done(err, rows[0]);
});
})
);
// route middleware to ensure user is logged in
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.sendStatus(401);
}
};
This is my Controller Class:
class AuthenticateController {
constructor(router, passport) {
this.router = router;
this.registerRoutes();
this.passport = passport;
}
registerRoutes() {
this.router.post('/login/:username/:password', this.login.bind(this));
//this.router.get('/logout', this.logout.bind(this));
this.router.get('/content', this.content.bind(this));
}
login(req, res) {
this.passport.authenticate("local-login", { failureRedirect: "/login"}),
res.redirect("/content");
}
content(req, res ) {
console.log(req.user);
if (req.isAuthenticated()) {
res.send("Congratulations! you've successfully logged in.")
} else {
res.sendStatus(401);
}
}
isLoggedIn(req, res, next) {
console.log(req.user);
if (req.isAuthenticated())
return next();
res.sendStatus(401);
}
}
module.exports = AuthenticateController;
The Controller gets the router and passport fully configured as parameters from my index.js.
//index.js
var express = require('express')
, cors = require('cors')
, app = express()
, passport = require('passport')
, morgan = require('morgan');
require('./config/passport')(passport); // pass passport for configuration
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(require('express-session')({secret: 'vidyapathaisalwaysrunning',
resave: true,
saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
var apiRouter = express.Router();
app.use('/api', apiRouter);
//
var apiV1 = express.Router();
apiRouter.use('/v1', apiV1);
var authenticateApiV1 = express.Router();
apiV1.use('/auth', authenticateApiV1);
var AuthenticateController = require('./controllers/authenticate');
var ac = new AuthenticateController(authenticateApiV1, passport); //pass in our fully configured passport
//If I call this /login instead of the /auth/login/ in the Controller Class it works!
//app.post("/login",
// passport.authenticate("local-login", { failureRedirect: "/login"}),
// function (req, res) {
// res.redirect("/content");
// });
What is working and what is not working
The Authentication in general is working. In my posted index.js you see app.post("/login", .... If I call this one the authentication is successfully and if I try to reach the restricted content in /auth/content/ req.user has a value (the user object) and I can successfully call req.isAuthenticated() .
BUT, If I use the authentication from /auth/login/username/password the req.user is undefined when trying to reach the restricted Content.
I get no error and the response of /auth/login/username/password/ HTTP Code 301 - 'redirecting to /content.
I have currently no idea what I´m doing wrong here and I´m pretty new to the topic of Node/express/ passport ..
Hope someone has an Idea. If you need something else to help me, just mention it in the comments and I will do my best to provide you everything you need.
Thanks
EDIT:
I recently tried to read the req.user in the login function and even there it is undefined
login(req, res) {
this.passport.authenticate("local-login", { failureRedirect: "/login"}),
console.log(req.user) //undefined
res.redirect("/content");
}
I guess it could be some async problem and I should use some callback functions, but I don´t know how to apply this in my login()
EDIT 2:
Another Issue I´m facing is the integration of the isLoggedIn() request.
If I do this:
registerRoutes() {
this.router.get('/', this.isLoggedIn, this.getUsers.bind(this));
this.router.get('/:id', this.getSingleUser.bind(this));
}
it results in 401 - Unauthorized
A console.log(req.user); in the isLoggedIn() results in undefined.
But if I call the first route without calling isLoggedIn() and do console.log(req.user); the user object exists.
The correct use of callback with passport authentication for local strategy can be as below:
function(req, res, next){
passport.authenticate('local-login', function(err, user, info){
if(err)
return logger.log('error', err);
if(user)
req.login(user, function(err){
if(err) return next(err);
return res.json({'success': true});
});
if(!user)
return res.json({'error':true, 'message': info.message, 'type': info.type});
})(req, res, next);
}
Please note the use of req.login() to explicitly set user in session.
The only thing I'm finding strange is that your route declarations are different.
In the AuthenticateController the route is declared as:
this.router.post('/login/:username/:password', ...
While in index.js, the route is simply declared as
app.post("/login", ...
How is your client submitting the login credentials to the server? If it is by form, like the tutorial, could it be that having :username and :password declared as route params but being sent by form messes with passport?
Try registering the route exactly like index.js
this.router.post('/login', ...
EDIT:
I've found another dicrepancy. In AuthenticateController the res.redirect("/content"); is not wrapped inside a callback. So it is being executed before Authenticate finishes running.
In the index.js example, passport is being used as a route middleware:
app.post("/login",
passport.authenticate("local-login", { failureRedirect: "/login"}),
function (req, res) {
res.redirect("/content");
});
While in the passport.js it is inside the callback. Consider declaring it in the route:
registerRoutes() {
this.router.post('/login', this.passport.authenticate("local-login", { failureRedirect: "/login"}), this.login.bind(this));
(...)
}
login(req, res) {
res.redirect("/content");
}
O, better yet, why not use passport's option to declare both success and failure redirects, since that seems to be all that you are doing:
login(req, res) {
this.passport.authenticate("local-login", { successRedirect: "/content", failureRedirect: "/login" });
}
You are passing this.login.bind(this) as a middleware to this.router.post('/login/:username/:password', this.login.bind(this)); but login(req, res) only responds to the request with res.redirect("/content"); i.e. redirecting to /content
So like you said, you need to supply a callback that does something with the user that is returned from passports middleware verify callback.
app.post("/login",
passport.authenticate("local-login", { failureRedirect: "/login"}),
function (req, res) {
console.log(req.user); // log user in console
res.json({user: req.user}); // send user as json response
});
The custom callback mentioned by #divsingh is if you want to explicitly have control of setting the session, error messages and redirecting the request. Any other information can be found under http://passportjs.org/docs