There is very strange behavior in Express, can't figure out, mind cracking problem.
So suppose in req.user I have user id and here is my middleware code.
app.use(function(req, res, next){
var User = mongoose.model('User');
User.findById(req.user, function(err, user){
if(err) return next(err);
res.locals.user = user;
console.log(user);
next();
});
}
So it is working just fine when request type is GET, but if request is POST it just get to infinite waiting, until I receive No data received.
There is no issues with database nor with session: console.log(user) always works.
This is very very strange... I even tried to use another async function and it didn't work again for POST only requests.
fs.stat(__dirname + '/schemas/user.js', function(err, stat){
next();
})
My conclusion is that if next() is being called from callback during POST request it just hangs, but who can explain me WHY???
The original issue that brings me here was when I was trying to use passport.js deserializer which reads user from mongodb for every request, so that fails too for POST only requests.
configurations
{
"name": "myApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "./node_modules/.bin/nodemon app.js"
},
"dependencies": {
"express": "3.0.0rc5", //did also tried with rc4
"ejs": ">= 0.8.3",
"express-partials": "latest",
"mongodb": ">= 1.1.7",
"mongoose": "*",
"node-uuid": "*",
"passport": "*",
"passport-local": "*",
"flashify": "*",
"nodemon": "latest"
}
}
express configuration
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.logger('dev'));
app.use(partials());
app.use(express.cookieParser('Secret secret'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(MY_MIDDLEWARE_HERE);
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(flashify);
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
I'm not sure this will have an effect, but its recommended to use bodyParser middleware earlier in the middleware stack. I would put it below cookieParser and above passport middleware, since many authentication mechanisms need to find parameters in the body.
Related
I'm trying to use express-session in nodejs express but I can't set or get sessions. I get "Property 'session' does not exist on type 'Request'" when I'm trying to build.
I tried to change the order of the codes but nothing works
node version : v10.15.3
visual studio : 2017
my dependencies
"dependencies": {
"axios": "^0.19.0",
"body-parser": "^1.19.0",
"cookie-parser": "^1.4.4",
"debug": "^2.2.0",
"express": "^4.14.0",
"express-session": "^1.16.2",
"pug": "^2.0.0-rc.3",
"session-file-store": "^1.3.0"
},
"devDependencies": {
"#types/debug": "0.0.30",
"#types/express": "^4.0.37",
"#types/express-serve-static-core": "^4.0.50",
"#types/mime": "^1.3.1",
"#types/serve-static": "^1.7.32",
"#types/node": "^6.0.87"
}
app.ts
var app = express();
var bodyParser = require('body-parser');
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded({ extended: true })); // to support URL-encoded bodies
app.use(session({
name: 'test-session-cookie-id',
secret: 'test',
resave: true,
store: new FileStore(),
saveUninitialized: true,
cookie: { secure: true }
}));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/signup', signup);
app.use('/verify', verify);
app.use(function printSession(req, res, next) {
console.log('req.session', req.session); //error
return next();
});
update :
module seems to be working fine itself . it created a session folder with 500+ files which is odd
update2 :
the express session is working fine but the error is bugging me. I uninstalled vs2017 and installed vs2019 and updated the typescript but the problem is still there
there was no #types/express-session in my dependencies/devDependencies . npm install --save #types/express-session did the job . there is no error now
I'm following a nodejs book here: https://www.packtpub.com/web-development/mean-web-development
All is going smoothly until I try and log in using the passport module. It just hangs with no errors. I have tried other solutions I've found on SO such as re-ordering the middleware, but I think they might be for different versions of Express, as some of the syntax looks slightly different (and doesn't work). Here are the relevant parts. Any help would be greatly appreciated!
Package.json:
{
"name": "MEAN",
"version": "0.0.3",
"description": "First mean app",
"dependencies": {
"express": "~4.8.8",
"morgan": "~1.3.0",
"compression": "~1.0.11",
"body-parser": "~1.8.0",
"method-override": "~2.2.0",
"express-session": "~1.7.6",
"ejs": "~1.0.0",
"connect-flash": "~0.1.1",
"mongoose": "~3.8.15",
"passport": "~0.2.1",
"passport-local": "~1.0.0"
}
}
express.js:
module.exports = function(){
var app = express();
if(process.env.NODE_ENV === 'development'){
app.use(morgan('dev'));
}else if(process.env.NODE_ENV === 'production'){
app.use(compress());
}
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(session({
saveUnitialized: true,
resave: true,
secret: config.sessionSecret
}));
app.set('views', './app/views');
app.set('view engine', 'ejs');
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
require('../app/routes/index.server.routes.js')(app);
require('../app/routes/users.server.routes.js')(app);
app.use(express.static('./public'));
return app;
};
passport.js
module.exports = function(){
var User = mongoose.model('User');
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(id, done){
User.findOne({
_id: id
}, '-password -salt'), function(err, user){
done(err, user);
};
});
require('./strategies/local.js')();
};
the routing:
app.route('/signin')
.get(users.renderSignin)
.post(passport.authenticate('local',{
successRedirect: '/',
failureRedirect: '/signin',
failureFlash: true
}));
Edit: it seems to be the passport.deserializeUser function where things break
Well I've gone to the passport docs, and pasted in the code from there, and it seems to work. So... any idea why the MEAN book example isn't working?
Code that worked:
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
I am using dustjs as the templating engine in an express app, and was wondering if anyone has successfully used the contextDump helper in a server side template in express? I followed the consolidate example for integrating dust with express, and it is working well. The helpers are there, as I'm able to do a simple test with the eq helper and it works. but when trying to dump the context I'm not seeing it anywhere. here is a sample template:
{>layout/}
{<content}
<ul>
{#users}
<li>{username} - Create New Task
<ul>
{#user.tasks}
<li>{title} - Delete Task |
Update Task</li>
{/user.tasks}
</ul>
</li>
{/users}
</ul>
{/content}
{#contextDump to="console"/}
Here's my app.js:
var express = require('express');
var app = express();
var http = require('http');
var path = require('path');
var db = require ('./models');
var dust = require('dustjs-linkedin');
var cons = require('consolidate');
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('models', db);
//configure dust
app.set('view engine', 'dust');
app.set('template_engine', 'dust');
app.engine('dust', cons.dust);
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//require routes
require('./routes')(app);
require('./routes/user')(app);
require('./routes/task')(app);
db
.sequelize
.sync({ force: true })
.complete(function (err) {
if (err) {
throw err;
} else {
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
}
});
and here's package.json:
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.4.6",
"sequelize": "~2.0.0-beta.5",
"mysql": "~2.0.0-rc2",
"lodash": "~2.4.1",
"async": "~0.2.9",
"dustjs-linkedin": "~2.2.2",
"dustjs-helpers": "~1.1.1",
"consolidate": "~0.10.0"
}
}
Thanks!
Modules:
"express": "~3.0.0",
"jade": ">= 0.0.1",
"mongoose": ">= 3.6.2",
"connect-mongo": "0.3.2",
"nodemailer": ">= 0.3.20",
"socket.io": "0.9",
"cookie": "0.0.5",
"passport": "0.2.3",
"passport-facebook": "*",
"underscore": "*"
-- BACKEND --
Expressjs Configuration:
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', config.root + '/app/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.limit('1mb'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser(''));
app.use(express.session());
app.use(express.static(path.join(config.root, 'public')));
// express/mongo session storage
app.use(express.session({
secret: '',
store: new mongoStore({
url: config.db,
collection : 'sessions'
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
});
In routers:
app.get('/login/facebook', passport.authenticate('facebook', { display: 'popup', scope: [ 'email', 'user_about_me'], failureRedirect: '/' }));
app.get('/login/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/' }), user.callbackLogin);
In user.callbackLogin :
exports.callbackLogin = function(req, res){
res.render('callback_login');
};
callback_login view has a js script to close the window login popup.
-- FRONTEND --
Utils.popupCenter = function(url, width, height, name) {
var left = (screen.width/2)-(width/2);
var top = (screen.height/2)-(height/2);
return window.open(url, name, "menubar=no,toolbar=no,status=no,width="+width+",height="+height+",toolbar=no,left="+left+",top="+top);
};
Utils.popupCenter('login/facebook', 600, 400, 'Facebook Login');
I'm having troubles with passportjs integration. The popup works, the facebook login is called, and when I click in 'Ok' the facebook returns the data and passport saves in mongodb. But, after this point, nothings works. Expressjs blocking the requests. When I try access another url nodejs stay busy. After spends some time I'm receiving the message "No data received".
I know it's quite late for an answer, but try this project that I put up together:
https://github.com/rafaelfaria/PassportJS-Facebook-Client-Auth
I hope that's what you are looking for.
I am following the peepcode (part 1) video tutorial on node.js, and I am getting stuck on the first few steps. When I try to go to http://localhost:3000/login, I get the following error:
500 Error: Failed to lookup view "/Users/dantang/Desktop/Programming/Node/basic server/hotpie/apps/authentication/views/login"
I'm guessing it is due to a typo, but I've tried changing the code several times and I can't figure out what is wrong. Would really appreciate it if someone could tell me what should I do? Thank you!
The github repo is https://github.com/tangbj/nodejs
Server.js
/**
* Module dependencies.
*/
require("coffee-script");
var express = require('express')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
//Routes
require('./apps/authentication/routes')(app);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
login.jade
form(action='/sessions', method='post')
label
| Username
input(type='text', name='user')
label
| Password
input(type='password', name='password')
input(type='submit', name='Submit')
routes.coffee
routes = (app) ->
app.get '/login', (req, res) ->
res.render "#{__dirname}/views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
package.json
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.1.0",
"jade": "*",
"coffee-script": "~1.6.1"
}
}
There was something wrong with your login.jade file. Maybe some encoding problem. I created a newLogin.jade file, changed the render function and everything works fine. See the pull request at github.
It will be unable to find the path if you are using Windows which requires backslash instead of forward-slash in linux. So use path.join or path.normalize to get correct paths.
Try to change this in your routes.coffee
res.render "#{__dirname}/views/login",
to
res.render path.join(__dirname, "/views/login"),
and
app.set('views', __dirname + '/views');
to
app.set('views', path.join(__dirname + '../views'));
Otherwise verify the location of the directories/files.