express.cookieSession() not saving data in the cookies - session

I am using parse.com dynamic website to build a product website. I want to use session cookie to store some data in bowser session cookie. Here is my app.js
var express = require('express');
var parseExpressHttpsRedirect = require('parse-express-https-redirect');
var parseExpressCookieSession = require('parse-express-cookie-session');
var app = express();
// Global app configuration section
app.set('views', 'cloud/views');
app.set('view engine', 'ejs');
app.use(parseExpressHttpsRedirect());
app.use(express.bodyParser());
app.use(express.cookieParser('YOUR_SIGNING_SECRET'));
app.use(parseExpressCookieSession({
cookie : {
maxAge : 3600000
}
}));
app.use(express.cookieSession());
app.use(app.router);
I have this method in app.js which is supposed to returned items added in the cart
function getProductsInCart(req) {
var productsInCart = req.session.productsInCart;
if(!productsInCart) {
return [];
}
return productsInCart;
}
And this is the method which adds a new product in the cart
app.get('/add-cart/*', function(req, res) {
var url = req.url;
var productId = url.split('/')[2];
var productsInCart = getProductsInCart(req);
productsInCart.push(productId)
req.session.productsInCart = productsInCart;
console.log("productsInCart: " + JSON.stringify(productsInCart));
});
The problem i am facing is that getProductsInCart method always returns an empty array, which means that the session is not storing the object in the cookie. This should be simple enough and i can't understand why its not working. Any pointer would be deeply appreciated.

There were two things i was doing wrong
using req.session instead of req.cookies
using cookies as a normal java script objects.
Here is the code that worked
app.get('/add-cart/*', function(req, res) {
var url = req.url;
var productId = url.split('/')[2];
var productsInCart = getProductsInCart(req);
console.log("productsInCart: " + JSON.stringify(productsInCart));
productsInCart.push(productId);
res.cookie('productsInCart', productsInCart, {
signed: false,
expires: new Date(Date.now() + 1000000)
});
res.send(req.cookies);
});
function getProductsInCart(req) {
var productsInCart = req.cookies.productsInCart;
if(!productsInCart) {
return [];
}
return productsInCart;
}

Related

(AWS) Getting RDS state via Lambda

I've been trying to retrieve the state of an RDS instance via Lambda in RDS, and I keep coming up short because I can't parse the response. I know I'm totally missing something here that's obvious. Here is the code:
var AWS = require('aws-sdk');
var rdsparams = {
DBInstanceIdentifier: 'mysql1'
};
module.exports = (instanceId) => {
var rds = new AWS.RDS();
var params = {
DBInstanceIdentifier: instanceId
};
var rdsResponse = rds.describeDBInstances(rdsparams, function (err,
data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
var resultData = {};
rds.describeDBInstances(rdsparams, function(err, data) {
if (err)
return context.done(err, null);
var rdsarray = {};
var rdsarray = (data);
console.log(rdsarray);
var ins = rdsarray[0];
console.log("Status: " + ins.DBInstanceStatus);
});
};
There's a lot going on with your code there!
The specific problem is that data isn't an array. Take a look at the response from the docs here: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/RDS.html#describeDBInstances-property
The array of returned values is in data.DBInstances. So those last few lines might be:
var rdsarray = data.DBInstances;
console.log(rdsarray);
var ins = rdsarray[0];
console.log("Status: " + ins.DBInstanceStatus);

Execute multiple http request - Parse Cloud Code

i have an array of stores, where the address and some other things are stored.
Now I want to iterate through this array and geocode the lat / lng coords and save them to the database.
With the code below I get double or triple entries of the same store. Do I miss something with the scope here?
Thanks!
var promises = [];
data.forEach(function (element, index)
{
var addressString = element.plz + " " + element.stadt + "," + element.adresse;
var url = encodeURI("https://maps.googleapis.com/maps/api/geocode/json?address=" +
addressString);
var promise = Parse.Cloud.httpRequest({
method: "GET",
url:url
}).then(function (http) //SUCCESS
{
var geocodedObject = new Parse.Object("GeocodedStores");
geocodedObject.set("storeID", element.id);
geocodedObject.set("Latitude", http.data.results[0].geometry.location.lat);
geocodedObject.set("Longitude", http.data.results[0].geometry.location.lng);
return geocodedObject.save(null, {
useMasterKey: true
});
},
function (http, error)
{
response.error(error);
});
promises.push(promise);
});
return Parse.Promise.when(promises);
Finally found a working solution. It looked like it was a problem with the scope. I put the code in a seperate function and added this returned promise to an array.
var fn = function(element, geocodedObject)
{
var addressString = element.plz + " " + element.stadt + "," + element.adresse;
var url = encodeURI("https://maps.googleapis.com/maps/api/geocode/json?address=" +
addressString);
Parse.Cloud.httpRequest({
method: "GET",
url: url
}).then(function(http)
{
geocodedObject.set("storeID", element.id);
geocodedObject.set("Latitude", http.data.results[0].geometry.location.lat);
geocodedObject.set("Longitude", http.data.results[0].geometry.location.lng);
geocodedObject.set("address", addressString);
return geocodedObject.save(null, {
useMasterKey: true
});
});
}
var promises = [];
for (var k = 0;k<data.length;k++)
{
var geocodedObject = new Parse.Object("GeocodedStores");
promises.push(fn(data[k], geocodedObject));
}
Parse.Promise.when(promises).then(function () {
response.success("DONE");
});

I need to connect my front-end Javascript code to my sever-side NodeJS code. How do I do this?

We are very new to programming and have a simple question. We are developing a very simple Google search app that searches strings on Google using client-server communication. We have a simple subset of Javascript here:
var firstName = some_string
var lastName = some_string
var googleSearch = firstName + lastName;
googleSearch = JSON.stringify(googleSearch);
We need to link this code to our NodeJS code to do the actual searching.
var google = require('google');
google.resultsPerPage = 25;
var nextCounter = 0;
google(googleSearch, function(err,res) { // Note googleSearch is from
// the frontend Javascript code
// that we want to pull the data from.
if (err console.error(err)
var link = res.links[0];
console.log(link.href);
var myLink = link.href;
})
We want to take the data from the googleSearch variable from our front-end code and utilize it in our server-side code. Then we want to display the data from myLink , which is in our server-side code, back into our front-end code.
What you need to do is make an Ajax request from your front end to your server.
If you use jquery, you can do something like this
$.ajax({
url: YOUR_SERVER_URL+"/getData",
data: {
"google_search": googleSearch,
},
method: "GET",
//use data type json if your server returns json
dataType: "json",
success: function(result) {
console.log("data fetched Successfully");
//result is the data your server returned.
console.log(result);
},
error: function() {
console.log("Something went wrong, data could not be fetched");
}
});
On your server side if you are using Express with Node,
you can return JSON by doing something like this:
var app = express();
app.get('/getData', function(req, res, next) {
var google = require('google');
google.resultsPerPage = 25;
var nextCounter = 0;
//getting query data that you passed from front end
var googleSearch = req.query.google_search;
google(googleSearch, function(err, res) {
if (err console.error(err) var link = res.links[0]; console.log(link.href);
var myLink = link.href;
})
//sending json data as response
res.json(myLink);
});
If you are using localhost, then your server url will be something like "https://localhost:5000".

Laravel IO Socket and redis over SSL https connection

Currently have IO sockets with laravel broadcasting with redis working perfectly. Until I then set up an SSL cert on the domain.
I have redis-server running on port 3001.
Then there is a socket.js set to listen to 3000.
My JS on the page I listen via io('//{{ $listen }}:3000').
Any guidance would be great on how to get this working over https. Would I just use 443 as the port?
Thanks.
My socket.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('notifications', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log('Message Recieved: ' + message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
First, setup your serverOptions object:
var serverOptions = {
port: 3000,
host: 127.0.0.1, //address to your site
key: '/etc/nginx/ssl/your_site/server.key', //Or whatever the path to your SSL is
cert: '/etc/nginx/ssl/your_site/server.crt',
NPNProtocols: ['http/2.0', 'spdy', 'http/1.1', 'http/1.0']
}
For the NPNProtocols, you may not care for all of them, but they're provided for reference.
Now just create the server:
var app = require('https').createServer(serverOptions),
io = require('socket.io')(app);
This should be pretty plug and play into your source at his point.\
As a side note your stuff is completely wide open and anyone can listen on your web socket, so nothing should be sent that is private through here. If you need to make your data private, then you're going to need 1 of two things;
Something like JWT-Auth Token
Something custom that interface with the Redis queue:
Here's an example of the latter:
var SECRET_KEY = '<YOUR_LARAVEL_SECRET_KEY>';
var laravel_session_parser = {
ord: function (string) {
return string.charCodeAt(0);
},
decryptSession: function (cookie, secret) {
if (cookie) {
var session_cookie = JSON.parse(new Buffer(cookie, 'base64'));
var iv = new Buffer(session_cookie.iv, 'base64');
var value = new Buffer(session_cookie.value, 'base64');
var rijCbc = new mcrypt.MCrypt('rijndael-128', 'cbc');
rijCbc.open(secret, iv);
var decrypted = rijCbc.decrypt(value).toString();
var len = decrypted.length - 1;
var pad = laravel_session_parser.ord(decrypted.charAt(len));
return phpunserialize.unserialize(decrypted.substr(0, decrypted.length - pad));
}
return null;
},
getUidFromObj: function (obj, pattern) {
var regexp = /login_web_([a-zA-Z0-9]+)/gi;
if (pattern) {
regexp = pattern;
}
var u_id = null;
for (var key in obj) {
var matches_array = key.match(regexp);
if (matches_array && matches_array.length > 0) {
u_id = obj[matches_array[0]];
return u_id;
}
}
return u_id;
},
getRedisSession: function (s_id, cb) {
var _sessionId = 'laravel:' + s_id;
client.get(_sessionId, function (err, session) {
if (err) {
cb && cb(err);
return;
}
cb && cb(null, session);
});
},
getSessionId: function (session, _callback) {
var u_id = null,
err = null;
try {
var laravelSession = phpunserialize.unserialize(phpunserialize.unserialize(session));
u_id = laravel_session_parser.getUidFromObj(laravelSession);
} catch (err) {
_callback(err, null);
}
_callback(err, u_id);
},
ready: function (socket, _callback) {
if (typeof socket.handshake.headers.cookie === 'string') {
var cookies = cookie.parse(socket.handshake.headers.cookie);
var laravel_session = cookies.laravel_session;
var session_id = laravel_session_parser.decryptSession(laravel_session, SECRET_KEY);
laravel_session_parser.getRedisSession(session_id, function (err, session) {
if (!err && session) {
laravel_session_parser.getSessionId(session, function (err, user_id) {
if (user_id) {
_callback(null, session_id, user_id, laravel_session)
} else {
_callback(new Error('Authentication error'), null);
}
});
} else {
_callback(new Error('Authentication error'), null);
}
});
}
}
};
Now you can just have IO get an instance of the individuals session when they establish a connection to socket.io
io.on('connection', function (socket) {
laravel_session_parser.ready(socket, function(err, session_id, user_id, laravel_session) {
//log out the variables above to see what they provide
});
});
Note, I prefer to use dotenv in NodeJS to share environment variables between Laravel and Node.
Then you can do process.env.APP_KEY and you don't need to worry about sharing variables.
Also of note, that script above is not complete and is not production ready, it's just meant to be used as an example.

how can I get sessions to work using redis, express & socket.io?

So I am trying to get Sessions to work inside my socket.on('connection', ...)
I am trying to get this working using recent versions: Socket.io - 0.9.13, Express - 3.1.0 and latest versions of other modules.
Anyway I have tried using both modules 'connect-redis' and 'session.socket.io' and they both have similar problems.
In my code I have 2 redis stores (socketio.RedisStore and require('connect-redis')(express)), now this program all runs fine, but because express and socket.io need to share session data, I was wondering if this setup will use sessions correctly? do the session stores need to be the same object for express/socketio? A bit of a gray area to me, because the 2 RedisStore's will use the same db in the background?
I have tried using either the socket.io redisStore or the connect-redis redisStore in both places, but socket.io doesnt like the connect-redis redisStore and express doesnt like the socketio.redisStore.
If I use the connect-redis RedisStore then socket.io/lib/manager.js complains:
this.store.subscribe(...
TypeError Object # has no method 'subscribe'
If I use socketio.RedisStore then express/node_modules/connect/lib/middleware/session.js complains:
TypeError: Object # has no method 'get'
*Note I would rather get the session.socket.io plugin working, but when I do the same setup with that plugin, express (also) complains:
TypeError: Object # has no method 'get'
So is it ok that I use 2 different RedisStores for sessions, or do I need to somehow get one or the other working for both, and if so any ideas on how to fix?
My current code looks like this:
var
CONST = {
port: 80,
sessionKey: 'your secret sauce'
};
var
redis = require('redis');
var
express = require('express'),
socketio = require('socket.io'),
RedisStore = require('connect-redis')(express);
var
redisStore = new RedisStore(),
socketStore = new socketio.RedisStore();
var
app = express(),
server = require('http').createServer(app),
io = socketio.listen(server);
app.configure(function(){
app.use(express.cookieParser( CONST.sessionKey ));
app.use(express.session({ secret: CONST.sessionKey, store: redisStore }));
app.use(express.static(__dirname + '/test'));
app.get('/', function (req, res) {res.sendfile(__dirname + '/test/' + 'index.htm');});
});
io.configure(function(){
io.set('log level', 1);
io.enable('browser client minification');
io.enable('browser client etag');
io.enable('browser client gzip');
io.set('store', socketStore);
});
io.sockets.on('connection', function(socket){
socket.emit('message', 'Test 1 from server')
});
server.listen( CONST.port );
console.log('running...');
inside the io.configure, you have to link the socket with the http session.
Here's a piece of code that extracts the cookie (This is using socket.io with xhr-polling, I don't know if this would work for websocket, although I suspect it would work).
var cookie = require('cookie');
var connect = require('connect');
var sessionStore = new RedisStore({
client: redis // the redis client
});
socketio.set('authorization', function(data, cb) {
if (data.headers.cookie) {
var sessionCookie = cookie.parse(data.headers.cookie);
var sessionID = connect.utils.parseSignedCookie(sessionCookie['connect.sid'], secret);
sessionStore.get(sessionID, function(err, session) {
if (err || !session) {
cb('Error', false);
} else {
data.session = session;
data.sessionID = sessionID;
cb(null, true);
}
});
} else {
cb('No cookie', false);
}
});
Then you can access the session using:
socket.on("selector", function(data, reply) {
var session = this.handshake.session;
...
}
This also has the added benefit that it checks there is a valid session, so only your logged in users can use sockets. You can use a different logic, though.
Looking at your last note (won't be able to share its state over multiple processes using redis) I had the same problem and found a solution:
var express = require("express.io");
var swig = require('swig');
var redis = require('redis');
var RedisStore = require('connect-redis')(express);
workers = function() {
var app = express().http().io();
app.use(express.cookieParser());
app.use(express.session({
secret: 'very cool secretcode',
store: new RedisStore({ client: redis.createClient() })
}));
app.io.set('store', new express.io.RedisStore({
redisPub: redis.createClient(),
redisSub: redis.createClient(),
redisClient: redis.createClient()
}));
app.get('/', function(req, res) {
res.render('index');
});
app.listen(3000);
app.io.route('ready', function(req){
//setup session stuff, use session stuff, etc. Or make new routes
});
};
cluster = require('cluster');
numCPUs = require('os').cpus().length;
if (cluster.isMaster)
{
for (var i = 0; i < numCPUs; i++)
{
cluster.fork();
}
}
else
{
workers();
}

Resources