node - continuation-local-storage - node.js

I am attempting to use the continuation-local-storage package to access the current express request/response from a point where that is not readily accessible.
I created the following middleware:
var createNamespace = require('continuation-local-storage').createNamespace,
getNamespace = require('continuation-local-storage').getNamespace;
const domain = 'ns.cls';
exports.configure = function(app) {
createNamespace(domain);
app.use(function(req, res, next) {
exports.set(req, res, "callcontext", { req, res });
next();
});
};
exports.set = function(req, res, name, value) {
var namespace = getNamespace(domain);
namespace.bindEmitter(req);
namespace.bindEmitter(res);
namespace.run(() => namespace.set(name, value));
};
exports.get = function(name) {
var namespace = getNamespace(domain);
return namespace.get(name);
};
exports.getCallContext = function() {
return exports.get("callcontext");
};
However when I attempt to access the context it is undefined:
var localStorage = require('../middleware/local-storage');
module.exports = function(doc, ctx) {
var callContext = localStorage.getCallContext();
console.log("value: " + callContext);
};
Does anyone have any ideas?
Thanks in advance,
Mark

createNameSpace should be called once. Also, you have an error on line
exports.set(req, res, "callcontext", { req, res });
should be something like
exports.set(req, res, "callcontext", { key: value });
This is the way I am using it:
to set
var session = require('continuation-local-storage').createNamespace('session')
app.use(function(req, res, next) {
session.bindEmitter(req);
session.bindEmitter(res);
session.run(function() {
session.set('req', req);
next();
});
});
to get
var session = require('continuation-local-storage').getNamespace('session')
session.get('req')

Related

how to get the api result from middleware to routes

I just wanted to get the result from the API in the middle ware that apply to routes. i am using express js the res.locals.wallet doesn't have a value
var request = require('request');
module.exports = function(req, res, next) {
if(req.session.active){
res.locals.active = req.session.active;
res.locals.email = req.session.email;
// res.locals.wallet = req.session.wallet;
res.locals.admin = req.session.admin;
res.locals.cart = req.session.cart;
res.locals.partner = req.session.partner;
var data = {
user_id :req.session.user_id,
}
request.post({
url : 'https://api.sample.com/frontend/sample',
form : data,
}, function (error, response, body) {
var bodyJson = JSON.parse(body);
console.log(bodyJson);
res.locals.wallet = req.session.wallet; <----- HERES THE PROBLEM
next();
});
} else {
res.redirect("/login");
}
next();
};
You call next immediate in your middleware, now res.locals.wallet value is undefined.
Just call next when you finish the job (call api).
var request = require('request');
module.exports = function(req, res, next) {
if(req.session.active){
res.locals.active = req.session.active;
res.locals.email = req.session.email;
// res.locals.wallet = req.session.wallet;
res.locals.admin = req.session.admin;
res.locals.cart = req.session.cart;
res.locals.partner = req.session.partner;
var data = {
user_id :req.session.user_id,
}
request.post({
url : 'https://api.sample.com/frontend/sample',
form : data,
}, function (error, response, body) {
var bodyJson = JSON.parse(body);
console.log(bodyJson);
res.locals.wallet = req.session.wallet; <----- HERES THE PROBLEM
next();
});
} else {
res.redirect("/login");
}
// next(); <----------------- remove this line
};

Is This Logic About Node.JS - Router True?

i'm new in node.js. i made routes/index like this and i don't know is it good or not?
my code worked perfectly but :
1 - can anyone explain is this code standard?
2 - can i use external folder/file for my controller ? like : controller/users/index.js
controller/api/index.js
routes/index.js
var express = require("express")
var router = express.Router()
var request = require("request");
let index = {
// ## Controls
getBTC: function () {
request.get("http://api.coindesk.com/v1/bpi/currentprice.json", (err, response, body) => {
if (err) {
return console.dir(err);
}
rate = JSON.parse(body).bpi.USD.rate
time = JSON.parse(body).time.updated
})
},
// ## Routes
indexRoute: function () {
router.get('/', function (req, res, next) {
res.render('common/index', {
title: 'Index Title',
rate: this.rate,
time: this.time
})
})
},
testRoute: function () {
router.get('/test', function (req, res, next) {
res.render('common/test', {
title: 'Test Title',
rate: this.rate
})
})
}
}
index.getBTC() //-> Enable For All Routes
index.indexRoute()
index.testRoute()
module.exports = router
views/common/index.pug
extends ../layout
block content
p #{rate}
h1 #{time}

Socket IO -- socket.emit firing every event twice

socket.js:
var state = {
io: null
}
exports.init = function(io) {
state.io = io;
}
exports.get = function() {
return state.io;
}
exports.emit = function(message, data) {
console.log("emitting")
state.io.emit(message, data);
}
exports.onConnection = function(callback) {
state.io.once('connection', function (socket) {
callback(socket);
});
}
tags.js:
router.get('/', function (req, res) {
var DeviceIdentifier = 'WILL'
var NDefRecord = 'FROM_WILL'
req.headers['x-name'] = DeviceIdentifier
req.headers['x-content'] = NDefRecord
console.log("tags.js: GET");
socket.emit("tag:scan", {name: "000000000a0d9439", content: "adsf});
})
server.js
var io = require('socket.io')(server);
var socket = require('./socket');
socket.init(io);
socket.onConnection(function (data) {
console.log("Got Connection");
console.log(data);
});
No matter how I am doing it, the socket.emit function is called twice and data is getting stored twice as well.
I've tried looking up many examples and the problem still seems like it is persisting
Any help would be appreciated.
Thanks!
just add res.send . you are not sending any response to the browser so he try to refresh after x seconds
router.get('/', function (req, res) {
var DeviceIdentifier = 'WILL'
var NDefRecord = 'FROM_WILL'
req.headers['x-name'] = DeviceIdentifier
req.headers['x-content'] = NDefRecord
console.log("tags.js: GET");
socket.emit("tag:scan", {name: "000000000a0d9439", content: "adsf});
res.send('ok');
})

handling session variables inside http.request in express

Hi. When i print the req.session.mySessValue in UI , the value is empty. I think the assigning of req.session.mySessValue = dt.myValue; (express-session) is not proper. could anyone help me on this. Thanks in advance.my express code is
router.get('/', function(req, res, next) {
if(!req.xx) {
return res.redirect('/firstView');
}
var options = {
.......
};
var call = http.request(options, function(resp) {
resp.on('data', function(dt) {
var jsondata = JSON.parse(dt);
req.session.mySessValue = dt.myValue;
});
});
call.end();
call.on('error', function(e) {
console.log("error" +e.message)
});
var v = {
title: 'sample',
req : req
}
res.render('myview', v);
});

Returned object is undefined, using dynamicHelpers

I've created an external file that's handling the dynamic helpers, which includes a bunch of functions that I want to be able to use from all my views.
In on of the functions I'm running a query and fetch tags from the database, which I want to use in my layout.jade file (that all other views is using). In the console, all seems ok. The query returns the tags object, but by some strange reason I can't return the object to the view, which gives me an error message telling me that "tags" is undefined".
This is the code in my file dynamicHelpers.js:
exports.tags = function(req, res){
var environment = require('../environment');
var service = require('../service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
query.exec(function (err, tags) {
if (err) {
console.log(err);
// do something
}
console.log(tags);
return tags;
});
}
in layout.jade i'm getting the object in this way (this shows undefined):
p
#{tags}
What I actually want to do is to loop through all the tags with 'each'. So a follow-up issue would be if this is allowed and possible (if 'tags' were not undefined)?
ul.tags
each tag in #{tags}
a(href='/tag/' + tag._id.toHexString())
li.tag= tag.name
UPDATE:
I've tried #Linus G Thiel's solution (see below), but can't get it to work (res.tags gets undefined). With console.log(tags) in the middleware, it prints out the object. However, in the dynamicHelper function below it gets undefined. Seems like res.tags doesn't get passed to the dynamicHelper by some reason.
dynamicHelpers.js:
exports.tags = function(req, res) {
console.log(req.tags); <--- undefined
return req.tags;
};
configuration.js:
module.exports = function(app, express, next){
app.configure(function() {
// lots of more app.use functions (eg. express.cookieParser());)
// ...
app.use(function(req, res, next) {
var environment = require('./environment');
var service = require('./service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
query.exec(function (err, tags) {
if (err) {
return next(err);
}
req.tags = tags;
next();
console.log(req.tags); <--- works fine
});
});
});
};
As #Exploit says in his comment, your tags function makes an async call to query.exec, which will finish after your tags function has returned. Express' helpers and dynamicHelpers can't be async, so you need to refactor this somehow. One way would be to put it on req in an earlier middleware or route, and then have a simple dynamicHelper which returns that:
dynamicHelpers.js:
exports.tags = function(req, res) {
return req.tags;
};
Middleware (you might not want to do this for all routes, you could look into e.g. Route specific middleware or Route param pre-conditions):
app.use(function(req, res, next) {
var environment = require('../environment');
var service = require('../service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
query.exec(function (err, tags) {
if (err) {
return next(err);
}
req.tags = tags;
next();
});
});
It's kinda dirty but you can do this to wait for tags to be set. The solution Linus G Thiel provided is better though because this will block your application.
tags: function(req, res) {
var environment = require('../environment');
var service = require('../service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
var _tags = false;
query.exec(function (err, tags) {
if (err) {
console.log(err);
// do something
}
console.log(tags);
_tags = tags;
});
while(_tags == false);
return _tags;
}
Have you tried it like this?
exports = function(app) {
app.dynamicHelpers({
tags: function(req, res) {
var environment = require('../environment');
var service = require('../service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
query.exec(function (err, tags) {
if (err) {
console.log(err);
// do something
}
console.log(tags);
return tags;
});
}
});
}
require("helpers")(app);
You need to defined the middleware before the other routes
module.exports = function(app, express, next){
app.configure(function() {
app.use(function(req, res, next) {
var environment = require('./environment');
var service = require('./service');
service.init(environment);
var model = service.useModel('tag');
var query = model.Tag.find({});
query.exec(function (err, tags) {
if (err) {
return next(err);
}
req.tags = tags;
next();
console.log(req.tags); <--- works fine
});
});
// lots of more app.use functions (eg. express.cookieParser());)
// ...
});
};

Resources