In my node.js app , I'm setting the session using async calls. I have used express-session for the session management. But setting the session behaves occasionally. I'm calling the 2 node.js routes using an angular app.
First time it will call the HTTP get calls and get all the data correctly. But only the last delayed route data will be set to the session. Not data from both route. Seems like setting the data from the delayed route is replacing the fast route session data. Here's my code.
Sometimes all the data is set to the session. (After 2 browser refreshes)
var express = require('express');
var http = require('http');
var request = require('request');
var bodyParser = require('body-parser');
var session = require('express-session');
var ejs = require('ejs');
var cookieParser = require('cookie-parser'); // the session is stored in a cookie, so we use this to parse it
var app = express();
app.set('views', __dirname + '/views');
app.set('port', process.env.PORT || 8081);
app.use(express.static(__dirname + '/app/'));
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.use(cookieParser());
app.use(session({
secret: '232332dfdffd',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 3600000 }}))
app.engine('html', ejs.renderFile);
var server = app.listen(8081,function(){
});
app.get('/route1', function(req, res , next) {
var data1 = req.session.data1;
if(data1){
console.log("Session is not null. Getting data1 from session");
res.status(200);
res.send(data1);
}else{
request({
url: "testUrl",
qs: {},
json: req.body,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}, function(error, response, body){
if(error) {
console.log("error "+error);
res.sendStatus(error);
} else {
req.session.data1 = response;
res.status(response.statusCode);
res.send(response);
}
});
}
});
app.get('/route2', function(req, res , next) {
var data2 = req.session.data2;
if(data2){
console.log("Session is not null. Getting data2 from session");
res.status(200);
res.send(data1);
}else{
request({
url: "testUrl2",
qs: {},
json: req.body,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}, function(error, response, body){
if(error) {
console.log("error "+error);
res.sendStatus(error);
} else {
req.session.data2 = response;
res.status(response.statusCode);
res.send(response);
}
});
}
});
Related
I am trying to identify the user that is on my application via sessionId, not actual info on the user account itself. However, what I am noticing is that the sessionId changes everytime the user performs an action on the page. As shown below. My goal would be to have the same sessionID from the point they open the webpage until they close it.
const app = require('express')();
const https = require('https');
const fs = require('fs');
const session = require('express-session');
function getDateTimestamp(){
var today = new Date();
var date = today.getFullYear()+'_'+(today.getMonth()+1)+'_'+today.getDate();
return date;
}
app.use(session({
resave: false,
saveUninitialized: true,
secret: 'whatever',
cookie: {
maxAge: 60*60*1000,
sameSite: true
}
}))
app.get('/', (req, res) => {
res.writeHead(200, {'Content-Type': 'text/html'});
var readStream = fs.createReadStream('index.html','utf8');
readStream.pipe(res);
});
app.post('/:fieldName/:flag/:time/:dashboard/:identifier/:user', (req, res) => {
console.log('POST message received', req.params);
if (req.params && req.params.fieldName) {
fs.appendFileSync(`./changeLog_${getDateTimestamp()}.csv`, `${req.params.fieldName},${req.params.flag},${req.params.time},${req.params.dashboard},${req.params.identifier},${req.params.user},${req.sessionID}\n`);
return res.send('OK')
}
res.status(400).end()
});
Client Side
function onParameterChange (parameterChangeEvent) {
parameterChangeEvent.getParameterAsync().then(function (param) {
parameterIndicator = 'Parameter'
const details = {
method: 'POST',
credentials: 'include'
//body: JSON.stringify(data),
// headers: {
// 'Content-Type': 'application/json'
// }
};
fetch(`url/${param.name}/${parameterIndicator}/${getDateTimestamp()}/${dashboardName}/${param.name}/${worksheetData}`, details).then((res) => {console.log(res);});
});
}
Here is my output showing a different session for the same user.
Just to illustrate my comment above, I actually have ran a quick test with a simple setup, and toggling saveUninitialized actually seems to make the difference:
// app.js
const express = require('express')
const app = express()
const session = require('express-session')
// Run the file as "node app false" or "node app true" to toggle saveUninitialized.
const saveUninitialized = process.argv[2] == "true" ? true : false
app.use(session({
resave: false,
saveUninitialized,
secret: 'whatever',
cookie: {
maxAge: 60 * 60 * 1000,
sameSite: true
}
}))
app.get("/", (req, res) => {
res.status(200).send(req.sessionID)
})
app.listen(3000, () => {
console.log('server started on http://localhost:3000')
})
// Response body
node app false
// 1st request: OTnFJD-r1MdiEc_8KNwzNES84Z0z1kp2
// 2nd request: 5UVVGng_G72Vmb5qvTdglCn9o9A4N-F6
// 3rd request: 9aGsAwnHh1p1sgINa1fMBXl-oRKcaQjM
node app true
// 1st request: StUrtHOKBFLSvl5qoFai6OQCm7TY87U-
// 2nd request: StUrtHOKBFLSvl5qoFai6OQCm7TY87U-
// 3rd request: StUrtHOKBFLSvl5qoFai6OQCm7TY87U-
But maybe there is more to it than that with your setup.
test.js - express code
var express = require('express');
var session = require('express-session');
const bodyParser = require('body-parser');
var app = express();
app.use(bodyParser());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(session({
secret: 'somerandonstuffs',
resave: false,
saveUninitialized: false
}));
app.listen(4000, () => {
console.log("server running on port....", 4000);
});
app.get('/getsession', function(request , response){
console.log("getsession::", request.sessionID);
if(request.session.uname){
response.json({username: request.session.uname});
} else {
response.json({username: "no user"});
}
});
app.post('/savesession', function(request , response){
request.session.uname = request.body.loginuname;
console.log("save session::", request.session);
response.json({username: request.session.uname});
});
app.js - user/client code
function login(){
$.ajax({
url: 'http://127.0.0.1:4000/getsession',
type: 'get',
dataType: 'json',
crossDomain: true,
success: function(result){
console.log( "result::: ", result );
},
error: function(xhr, resp, text){
console.log("xhr:: ", xhr , "resp::: ", resp , "text::: ", text);
}
});
$("#ahrefbtn").on('click', function(){
var data = $("#formdata").serializeArray();
$.ajax({
url: 'http://127.0.0.1:4000/savesession',
type: 'post',
dataType: 'json',
data: data,
success: function(result){
console.log( "result::: ", result );
},
error: function(xhr, resp, text){
console.log("xhr:: ", xhr , "resp::: ", resp ,
"text::: ", text);
}
});
$(document).ready(function(){
login();
});
Above code works fine for postman get and post requests.
But when I use browser-chrome(session cookies allowed) on page reload/refresh it creates new sessionid and each time new session is getting generated.
How do i get same session each time to retrieve last session data.
In app.js on page reload/refresh it calls getsession api and on button click it it calls savesession api.
app.js api calls are executes properly.
I'm trying to use body-parse version 1.18.3 with express to parse a json post. In app.js I've included it like so
app.js
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
...
//App setup
var app = express();
// create application/json parser
var jsonParser = bodyParser.json()
app.set('trust proxy', 1) // trust first proxy
// Use the session middleware
app.use(session({ secret: 'secretletters', cookie: {}}))
app.post('/', jsonParser, function (req, res) {
console.log(req.body);
if (req.session.username) {
} else {
}
res.send({'status': 'ok'})
});
and in my script on the frontend send a username back to it
$('.login-btn').click(function() {
let username = $('.username').val();
if (username == '') {
$('.login-error').removeClass('hidden');
return null;
}
//if passed hide error
$('.login-error').addClass('hidden');
var data = {
'username': username
}
$.ajax({
url: "/",
type: "POST",
dataType: 'json',
data: JSON.stringify(data),
success: function(response){
},
error: function(xhr){
},
});
/* End Ajax Call */
});
It send the username successfully, here's a screenshot of the results of the post request from the network tools
the bug is when on console.log(req.body); on app.post I get back and empty {} dict
I have an unexpected behavior when using isomorphic-fetch vs. request-promise related to Express sessions (and Express session ID in particular):
As part of the troubleshooting process, I implemented two methods in client.js for calling endpoints in server.js: 1) isomorphic-fetch, and 2) request-promise.
Client.js
// Method 1: isomorphic-fetch
require('es6-promise').polyfill();
require('isomorphic-fetch');
fetch('http://localhost:3000', {
credentials: 'same-origin',
})
.then(function(response) {
console.log(response.status);
});
fetch('http://localhost:3000', {
credentials: 'same-origin',
})
.then(function(response) {
console.log(response.status);
});
// Method 2: request-promise
var rp = require('request-promise').defaults({
jar: true
});
function requestPage() {
return rp('http://localhost:3000/');
}
requestPage()
.then(console.dir)
.then(requestPage)
.then(console.dir)
.catch(console.error);
Server.js
var app = require('express')();
app.use(require('morgan')('dev'));
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(session({
name: 'server-session-cookie-id',
secret: 'my express secret',
saveUninitialized: true,
resave: true,
store: new FileStore(),
cookie: {
secure: false
}
}));
app.get('/', function initViewsCount(req, res, next) {
console.log('req.session.id = ' + req.session.id);
if (typeof req.session.views === 'undefined') {
req.session.views = 1;
return res.end('Welcome to the file session demo. Refresh page!');
}
return next();
});
app.get('/', function incrementViewsCount(req, res, next) {
console.assert(typeof req.session.views === 'number',
'missing views count in the session', req.session);
req.session.views++;
return next();
})
app.use(function printSession(req, res, next) {
console.log('req.session', req.session);
return next();
});
app.get('/', function sendPageWithCounter(req, res) {
res.setHeader('Content-Type', 'text/html');
res.write('<p>views: ' + req.session.views + '</p>\n');
res.end();
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
When I execute node client.js, here is the output of the server:
req.session.id = deWKCvqcyGiAvVSUvHv2Db7sjvE7xN1E
req.session.id = MxLHWjbMMvV4GRfPSf6sQ12XvauiJJot
req.session.id = A3KTLMdBopQ7pAfcTsJhnzzdokdA7hGI
GET / 200 1.407 ms - -
GET / 200 7.625 ms - -
GET / 200 0.728 ms - -
req.session.id = A3KTLMdBopQ7pAfcTsJhnzzdokdA7hGI
req.session Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false },
views: 2,
__lastAccess: 1517449125197 }
GET / 200 6.902 ms - -
I confirmed that method 2 (request-promise) successfully persists the session on the server. In other words, session A3KTLMdBopQ7pAfcTsJhnzzdokdA7hGI is associated with this method.
However, as observed from the output, method 1 (isomorphic-fetch) generates two separate sessions on the server.
Question: Why does isomorphic-fetch create two separate sessions on the server?
Troubleshooting performed:
I replaced localhost with 127.0.0.1, but this did not change the behavior.
I replaced same-origin with include, but this did not change the behavior.
Environment:
node v6.10.3
isomorphic-fetch 2.2.1
request-promise 4.2.2
I don't get the Bodyparser middleware in Express to work. What can be the problem?
My code:
Node.js:
var express = require('express')
, app = express()
, expressLayouts = require('express-ejs-layouts');
app.set('view engine', 'ejs');
app.set('layout', 'myLayout'); // defaults to 'layout'
app.use(expressLayouts);
app.use(app.router);
app.use(express.bodyParser()); // <- Problem with this
app.get('/', function(req, res){
res.render('aView.ejs', { layout: 'template.ejs' }) // it renders HTML & script
});
app.post('/myroute/', function(req, res) {
console.log("output if this works"); // this works
if(req.body) // this results in false
console.log("From client: "+ req.body.param(1, null) );
else // else is run
console.log("Client to server AJAX doesn't work");
res.send( JSON.stringify({ test : 'Server to client AJAX work'}) ); // works
});
console.log("Node.js server is running");
app.listen(3000);
Client code (jQuery 1.7.1)
function test()
{
alert("this 2"); // this works
getA(function(dat)
{
alert("this 4: "+dat.test); // this works
});
}
function getA(callback) {
$.ajax({
url: '/myroute/',
type: 'POST',
dataType: 'json',
data: ['test 1','2', '4', '6'],
success: function(data) { if ( callback ) callback(data); },
error: function() { if ( callback ) callback(null); },
complete: function() { alert("Klart"); }
});
}
You have the router before the body parser (So by the time it gets to your handler, bodyParser has not been called.) Place bodyParser before app.router