Restify set method like in Express - node.js

In Express 4.0, after declaring the server I do the following to set a server-wide variable...
var app = express();
app.set('foo', 'bar');
I don't see a method like that in Restify's documentation, so I'm just declaring an object inside the server that holds my variables.
Is that correct? Is there a better way to do this in Restify?

It sounds like that would work, but why not just create a module to hold your variables? Create a file named vars.js somewhere appropriate and make it like this:
module.exports = {
my_var: 2112,
other_var: 'signals'
}
Then wherever you need access to those variable just
var all_vars = require('./path/to/var.js');
and you'll have them.

Related

Instantiate node module differently per (web) user

I was wondering what the best practice is for the following scenario:
I am planning to use an npm module for a web servie, where the user enters a access and secret key. Then a module is used which is instantiated like this:
var module = require('module')('ACCESS_KEY','SECRET_KEY');
Each user of course has a different access and secret key. The module exposes several functions which I want to use with the user's access and secret key on his behalf.
Now my question is, how I can 'require' that module with the keys from the database for each user, not just for the whole application with a single static pair. I am on node 8 and using ES6.
The crucial detail here is that this:
var module = require('module')('ACCESS_KEY','SECRET_KEY');
...is equivalent to this:
var moduleFunc = require('module');
var module = moduleFunc('ACCESS_KEY', 'SECRET_KEY');
In other words, 'module' exports a function, and you're calling that function with two arguments ('ACCESS_KEY', 'SECRET_KEY') and assigning the result to module.
That means you can instead require('module') at the top of your file and then use the function it gives you as many times as you want later on, with different arguments.
For example:
const someApi = require('some-api');
// ...later...
app.get('/', (req, res) => {
const { ACCESS_KEY, SECRET_KEY } = getUserKeys(req);
const apiClient = someApi(ACCESS_KEY, SECRET_KEY);
// ...
});

Application-scope Variables in Node.js?

Is there a variable scope in Node.js that persists longer than the request, that is available to all application users? I'd like to create a variable that can be read/written to by multiple app users, like so:
var appScope.appHitCount += 1;
The session scope won't work because it is user specific. Looking for application specific. I couldn't find anything in the Node.js docs. Thanks.
If you have a variable scoped to the app module it will be available and shared by everything within the scope. I imagine in a big app you would need to be careful with this, but it's just regular javascript scoping. For example this will continue to append to the array as you hit it:
const express = require('express')
const app = express()
var input = []
app.get('/:input/', (req, res) => {
var params = req.params
input.push(params.input)
res.send("last input was: " + JSON.stringify(input))
})
app.listen(8080, () => console.log('Example app listening on port 8080!'))
Now visiting 'http://localhost:8080/hi' returns:
last input was: ["hi"]
and then 'http://localhost:8080/there' returns:
last input was: ["hi", "there"]
...etc.
If you want something shared by the entire app (i.e. all the modules) you could set up a module that is require()d by all the modules and i=has the responsibility of getting and setting that value.

What doesn't nodejs relate 'this' as the object that encapsulates the function?

I wrote the following code in nodejs:
var express = require('express');
var app = express();
app.message = "helloworld";
app.get('/check', function (req,res) {
res.end("GET request OK");
console.log(this.message);
});
app.listen(4000);
When I run the code and send a GET request, the line:
console.log(this.message);
prints "undefined".
However, when I change it to:
console.log(app.message)
I get "helloworld".
I thought that this variable should represent the object that invoked the function. If so, why doesn't this object include the attribute .message ?
this can be whatever the author of the library intends it to be. It could be the app instance or it could be the global object.
In this case, it appears it's the global object.
As a sidenote too, it's not recommended to add expando properties to an existing library like that.

node js - are modules shared between users?

Given the following module:
module.exports = function() {
var env;
var module = {};
module.setEnv= function(myEnv) {
env = myEnv; // env may be set to a different value per user
}
module.doActionWithEnv = function() {
...
}
...
return module;
}
I require the module like so:
var myModule = require('/myModule')();
Now my question is, is my module shared between 2 different users that visit the site? By that I mean, can collisions occur if one user sets the private env variable, and then the other calls some function inside the module that depends on env and thus gets the wrong result?
Thanks.
Variables on your server are generally once per server process, not once per user making a request. Some variables like the req and res objects passed to a request handler are uniquely created for each request. Per user variables will typically need some sort of session management layer to allow the server to identify which user is making the request and to then access data stored for that specific user. You can read Express Sessions or Node.js and Express Sessions or Express.js Sessions – A Detailed Tutorial for more info about using sessions in Express and there are a number of NPM modules for implementing sessions with Express though express-session is likely the most popular.
To explain about your code, in this line of your code:
var myModule = require('/myModule')();
You will get a new myModule for every call to that. So, each time you call that module constructor, you get a new myModule object that has a new env inside of it.
But, if you just call that constructor once and have only one myModule variable in your code and multiple requests from your web server on behalf of different users are all using that same myModule variable, then they will all be sharing the same myModule object and thus the same env variable inside of it.
What makes your situation a bit confusing is that modules in node.js that are created when you do require('/myModule') are cached and shared in node.js. So, there is only one actual myModule.js loaded module as far as the node.js system is concerned. But, each time you call the module constructor, your own code creates a new object (which you also named module which makes things confusing). So, if you call that constructor 5 times such as:
var m = require('/myModule');
var x1 = m();
var x2 = m();
var x3 = m();
var x4 = m();
var x5 = m();
Or even:
var x1 = require('/myModule')();
var x2 = require('/myModule')();
var x3 = require('/myModule')();
var x4 = require('/myModule')();
var x5 = require('/myModule')();
Then, you will have 5 separate objects in the variables x1 through x5 and each will have their own env variables inside.
But, if you just do this once:
var myObj = require('/myModule')();
myObj.setEnv("hello");
And, then multiple request handlers all refer to that myObj object like this:
app.get('/request1', function(req, res) {
myObj.setEnv("goodbye");
}};
app.get('/request2', function(req, res) {
myObj.setEnv("adios");
}};
Then, both of these request handlers will be operating on the same myObj object no matter what user initiates the request.
How can I avoid this problem then?
If you want per-user information stored on your server, then you would typically use sessions. While there are many ways to implement a session, they usually set a unique cookie for each user's browser when they first visit your site. There is then a storage mechanism on the server that can access data that belongs to the user with that cookie value. You don't use normal JS variables for storing each user's state. You would typically use either an object lookup (by cookie ID) or some sort of database.
Since it looks like you are using Express, there are several NPM modules that will hook into Express and implement sessions for you. The most popular session implementation for Express is express-sessions.

Global variable across all controllers in Node JS

I am trying to have a variable which can be accessible by all controllers in my node project. Currently in one controller I have:
var ua = req.headers['user-agent'];
var isMobile = "no";
if(/mobile/i.test(ua))
isMobile="yes";
It's pointless to copy past all of this for all my controllers and pass the isMobile variable to the view. I'd like to get the value of isMobile set once, and then pass it wherever I want from my controllers.
Is there an easy way to do this rather than have those 4 lines of code copy pasted in every controller?
Thanks
You'll want to use a Sails policy for this:
// /api/policies/isMobile.js
module.exports = function(req, res, next) {
var ua = req.headers['user-agent'];
req.isMobile = /mobile/i.test(ua);
next();
}
// /config/policies.js
module.exports.policies = {
'*': 'isMobile'
};
This will run the code before every controller action, and give you access to the req.isMobile var in all of your custom controller code.
A truly global variable isn't particularly an option as any concurrency above 1 will likely result in unexpected behavior. Being that it is something particular to the unique request itself, the req object is likely your best bet.
Assuming you have access to the req object everywhere that you would like to utilize use this flag, you can simply add a property to the req object at any point (preferably early in the request/response cycle). After this property is added, it should be available everywhere that has access to req.
req.isMobile = /mobile/i.test(req.headers['user-agent']) ? 'yes' : 'no';
Or if there is a concept like middleware in express for sails
function isMobile(req, res, next) {
req.isMobile = /mobile/i.test(req.headers['user-agent']) ? 'yes' : 'no';
next();
}

Resources