Express-resource pass additional data from app.js to routes - node.js

I would like to pass additional data from app.js to express-resource routes and I have not figured out yet. How would you do that? Note that I'm using express-resource
// app.js
var myAddOnData = 'abc';
app.resource('users', './routes/user');
// user.js
exports.index = function (req, res) {
console.log(myAddOnData);
};
Thanks

These are the three approaches I can think of. Without the little I know about your specific problem, it sounds like middleware might be the way to do it.
With a global app variable
Create a value using app.set in app.js and then retrieve it using app.get in user.js.
Using a module
Store the information in an isolated module, then require() as needed. If this is running across multiple instances, you'd obviously want to store the values to disk as opposed to in memory.
// keystore.js
// -----------
module.exports.set = function(id, val) { /* ... */ };
module.exports.get = function(id) { /* ... */ };
// app.js
// -----------
var ks = require('./keystore');
ks.set = function("userInfo", "abc");
module.exports.get = function(id) { /* ... */ };
// user.js
// -----------
var ks = require('./keystore');
ks.get = function("userInfo", "abc");
(Maybe check out pot?)
Using Middleware
Use custom middleware to attach data to the request object which can then be accessed later in the route handlers.
//app.js
//------
var express = require('express')
, cookieSessions = require('./cookie-sessions');
var app = express();
app.use(express.cookieParser('manny is cool'));
app.use(cookieSessions('sid'));
// ...
//cookie-sessions.js
//------------------
module.exports = function(name) {
return function(req, res, next) {
req.session = req.signedCookies[name] || {};
res.on('header', function(){
res.signedCookie(name, req.session, { signed: true });
});
next();
}
}
via https://gist.github.com/visionmedia/1491756

Related

How do I access the logged in user object in a view?

Once a user has been logged in, how do I reference this.req.user from inside of a view?
I think this would involve updating the locals collection of the Jade middleware. I haven't been able to get a reference to this object though.
Up until now I've been doing the following...
app.use(jade.middleware({
viewPath: __dirname + '/views',
debug: true,
pretty: true,
compileDebug: true,
locals: {
moment: require('moment'),
_: require('lodash')
}
}));
And then in the view there'd be something like this...
span=moment(new Date(item.date)).calendar()
Of course now I have a user object that cannot be assigned at set-up.
There are a few libraries you could use, here is how you would do it with co-views:
'use strict';
let koa = require('koa'),
views = require('co-views');
let app = koa();
let render = views(__dirname + '/jade/', {default: 'jade'});
app.use(function *controller(){
let data;
data = {
user: this.req.user
};
this.body = yield render('jadeFileName', data);
});
I made a screencast on serving content from Koa with Jade which might be helpful. You can find it at:
http://knowthen.com/episode-6-serving-content-in-koajs-with-jade/
EDIT:
Here is an option in response to your desire to not pass the user when calling render.
'use strict';
let koa = require('koa'),
views = require('co-views');
let app = koa();
let render = views(__dirname + '/jade/', {default: 'jade'});
// using custom middleware
app.use(function *(next){
this.render = function (fileName, data){
data = data || {};
data.user = this.req.user;
return render(fileName, data);
}
yield next;
});
app.use(function *controller(){
this.body = yield this.render('jadeFileName');
});
In your express configuration, you need to store the user object in res.locals after you authenticate the user, something like this works:
app.use(function(req, res, next){
res.locals.user = req.user;
next();
});
Then you should be able to reference the user in your jade templates:
block content
p= user.email

Use node js domains in handler function

I have https server written in express js. And I added domains to my server. App.js file:
var d = require('domain').create();
d.on('error', function(error) {
console.error("Domain caught error: "+ error.stack);
});
d.run(function() {
var express = require('express');
var appServer = express();
var https = require('https').createServer(options, appServer);
https.listen(8000, function() {
log.info('Server is listening on port ' + 8000);
});
appServer.use(appServer.router);
var routes = require('./routes')(appServer); //my routes file
});
I have route handler functions in other files. How can I use domain created in my app.js file in my route files without exporting it from app.js file.
Update:
routes.js file:
var auth = require('./auth');
module.exports = function(app) {
app.namespace('/login', function(){
app.post('/user', auth.verifyUser);
});
};
auth.js file:
exports.verifyUser = function(req,res) {
//here I want to see my domain
};
You can pass it when you require your routes:
var routes = require('./routes')(appServer, d);
Then within your routes/index.js file:
module.exports = function(app, domain) {
// ...
};
Update
To update the answer based on the question update, here's a possible solution to include the domain within each route definition. There are a couple ways to do this (you could make each route a class, which would be instantiated and passed the domain, then have a function defined per route, for example). Because the intent is to keep these route definition signatures function(req, res) as you've defined above for verifyUser, we're going to need to pass the domain to this route prior to calling the function. Keeping this very simple, we can do just that with a setDomain function:
Same code in your main index.js when you require your routes:
var routes = require('./routes')(appServer, d);
In your routes.js, you can pass the domain to the routes via the setDomain function:
var auth = require('./auth');
module.exports = function(app, domain) {
auth.setDomain(domain);
app.namespace('/login', function() {
app.post('/user', auth.verifyUser);
});
};
Finally, in your auth.js file, you can get the domain, and have access to it within the scope of the file to use it in the verifyUser function:
var myDomain;
module.exports.setDomain = function(domain) {
myDomain = domain;
};
module.exports.verifyUser = function(req, res) {
res.send("myDomain: " + myDomain);
};
I'm not sure I really like this solution, but again, it's keeping the signature the same for verifyUser. Maybe you'll think of a better one, or want to refactor your code to better make use of this domain you're passing around within your code (maybe define it somewhere else and pull it from there wherever it's needed).

How to pass variable from app.js to routes/index.js?

I'm using shrinkroute https://npmjs.org/package/shrinkroute to make links in nodejs. I get error 500 ReferenceError: shrinkr is not defined
How to pass shrinkroute to routes/index.js? Is there a better way to create url by passing query string args?
//app.js
var app = express();
var shrinkr = shrinkroute( app, {
"user": {
path: "/user/:id?",
get: routes.showOrListUsers
}
});
//url method works in app.js
var url = shrinkr.url( "user", { id: 5, page:40, type:'a' } );
console.log(url);
app.use( shrinkr.middleware );
//routes/index.js
exports.showOrListUsers = function(req, res, next) {
console.log(req.params);
//shrinkr errors out in index.js
var url2 = shrinkr.url( "users", {name: "foo"});
console.log(url2);
}
One solution would be to store shrinkr in your app object using app.set:
// app.js
...
app.set('shrinkr', shrinkr);
...
In routes/index.js, you can access it through the req.app or res.app objects:
exports.showOrListUsers = function(req, res, next) {
var shrinkr = req.app.get('shrinkr');
...
};
A bit late to the party, but the following works as well:
app.js
var my_var = 'your variable';
var route = require('./routes/index')(my_var);
app.get('/', route);
and meanwhile in route.js
var express = require('express')
, router = express.Router()
// Router functions here, as normal; each of these
// run only on requests to the server
router.get('/', function (req, res, next) {
res.status(200).end('Howdy');
});
module.exports = function(my_var){
// do as you wish
// this runs in background, not on each
// request
return router;
}
Two easy ways to achieve what you want:
1. Accessing your shrinkroute instance from within your route
Simple as that. Nothing else is required after Shrinkroute is setup.
exports.showOrListUsers = function(req, res, next) {
var shrinkr = req.app.shrinkroute;
console.log( "Route: " + req.route.name ); // ta-da, made available by Shrinkroute
// do your URL buildings
};
2. Using the middleware
If you don't want be tempted with non URL building methods of Shrinkroute, you can use the middleware, which will make available to you some helpers in your route and in your template (via locals):
// app.js
app.use( shrinkr.middleware );
// routes/index.js
exports.showOrListUsers = function(req, res, next) {
console.log( "Route: " + req.route.name ); // ta-da, made available by Shrinkroute
req.buildUrl( "users", { name: "foo" } );
// or, if you want the full url with the scheme and host...
req.buildFullUrl( "users", { name: "foo" } );
};
And maybe you want to use them in your templates as well?
// templates/index.jade
a( href=url( "users", { name: "foo" } ) ) Foo profile
a( href=fullUrl( "users", { name: "foo" } ) ) Foo profile
This method has the advantage that you don't get direct access to route setters inside a route.
Disclaimer: I'm the author of Shrinkroute.
you should import it. add following line to the very beginning of your code
var shrinkroute = require('shrinkroute');

nodejs access main script context

Diving into node, I have a question on how an included script, can access the main's script methods or variables
For instance, say that I have a logger object initiated in the main script and I include another js file, which needs access to the logger. How can I do that, without injecting the logger to the included script.
//main node script
var logger = require('logger'),
app = require("./app.js")
//app.js
function something(){
//access logger here !!!!!!!
}
exports.something = something
Hope it is clear
Thanks
Try doing:
//main node script
var logger = require('logger'),
app = require("./app.js")(logger);
//app.js
var something = function (logger){
logger.log('Im here!');
}
module.exports = exports = something;
Edit:
If you want to split your main app's code into different files, on your main script file you can do something like: (This is how I'm splitting my main app.js into different sections)
// main app.js
express = require('express');
...
/* Routes ---------------------*/
require('./config/routes')(app);
/* Socket IO init -------------*/
require('./app/controllers/socket.io')(io);
/* Your other file ------------*/
require('./path/to/file')(app);
...
// config/routes.js
module.exports = function(app){
app.configure(function(){
app.get('/', ...);
...
}
}
// app/controllers/socket.io.js
module.exports = function(io){
// My custom socket IO implementation here
}
// ...etc
Edit 2:
Your function can also return a JS object, in case you want to do something on the main app.js with a custom script.
Example:
// main app.js
...
/* Some controller ---------------------*/
var myThing = require('./some/controller')(app);
myThing.myFunction2('lorem'); // will print 'lorem' on console
...
// some/controller.js
// Your function can also return a JS object, in case you want to do something on the main app.js with this require
var helperModule = require('helperModule');
module.exports = function(app){
var myFunction = function(){ console.log('lorem'); }
// An example to export a different function based on something
if (app.something == helperModule.something){
myFunction = function() { console.log('dolor'); }
}
return {
myFunction: myFunction,
myFunction2: function(something){
console.log(something);
}
}
}
You can also simply export a function or an object containing functions, without sending any parameter like this:
// main app.js
...
var myModule = require('./path/to/module');
myModule.myFunction('lorem'); // will print "lorem" in console
...
// path/to/module.js
module.exports = {
myFunction: function(message){ console.log(message); },
myFunction2: ...
}
Basically, whatever you put inside module.exports is what gets returned after the require() function.
module.exports is what is returned when you require the file. in #DavidOliveros example, that's a function that takes app or io as parameters. the function is executed right after the require takes place.
If you want to expose a method of the included script to the main, try this:
// child.js
module.exports = function(app){
var child = {};
child.crazyFunction = function(callback){
app.explode(function(){
callback();
});
};
child.otherFunction = function(){};
return child;
};
// app.js
var express = require('express');
var app = module.exports = express();
var child = require('./child.js')(app);
app.get('/', function(req, res){
child.crazyFunction(function(){
res.send(500);
});
});

Global Variable in app.js accessible in routes?

How do i set a variable in app.js and have it be available in all the routes, atleast in the index.js file located in routes. using the express framework and node.js
It is actually very easy to do this using the "set" and "get" methods available on an express object.
Example as follows, say you have a variable called config with your configuration related stuff that you want to be available in other places:
In app.js:
var config = require('./config');
app.configure(function() {
...
app.set('config', config);
...
}
In routes/index.js
exports.index = function(req, res){
var config = req.app.get('config');
// config is now available
...
}
A neat way to do this is to use app.locals provided by Express itself.
Here is the documentation.
// In app.js:
app.locals.variable_you_need = 42;
// In index.js
exports.route = function(req, res){
var variable_i_needed = req.app.locals.variable_you_need;
}
To make a global variable, just declare it without the var keyword. (Generally speaking this isn't best practice, but in some cases it can be useful - just be careful as it will make the variable available everywhere.)
Here's an example from visionmedia/screenshot-app
file app.js:
/**
* Module dependencies.
*/
var express = require('express')
, stylus = require('stylus')
, redis = require('redis')
, http = require('http');
app = express();
//... require() route files
file routes/main.js
//we can now access 'app' without redeclaring it or passing it in...
/*
* GET home page.
*/
app.get('/', function(req, res, next){
res.render('index');
});
//...
To declare a global variable you need do use global object. Like global.yourVariableName. But it is not a true way. To share variables between modules try to use injection style like
someModule.js:
module.exports = function(injectedVariable) {
return {
somePublicMethod: function() {
},
anotherPublicMethod: function() {
},
};
};
app.js
var someModule = require('./someModule')(someSharedVariable);
Or you may use surrogate object to do that. Like hub.
someModule.js:
var hub = require('hub');
module.somePublicMethod = function() {
// We can use hub.db here
};
module.anotherPublicMethod = function() {
};
app.js
var hub = require('hub');
hub.db = dbConnection;
var someModule = require('./someModule');
the easiest way is to declare a global variable in your app.js, early on:
global.mySpecialVariable = "something"
then in any routes you can get it:
console.log(mySpecialVariable)
This was a helpful question, but could be more so by giving actual code examples. Even the linked article does not actually show an implementation. I, therefore, humbly submit:
In your app.js file, the top of the file:
var express = require('express')
, http = require('http')
, path = require('path');
app = express(); //IMPORTANT! define the global app variable prior to requiring routes!
var routes = require('./routes');
app.js will not have any reference to app.get() method. Leave these to be defined in the individual routes files.
routes/index.js:
require('./main');
require('./users');
and finally, an actual routes file, routes/main.js:
function index (request, response) {
response.render('index', { title: 'Express' });
}
app.get('/',index); // <-- define the routes here now, thanks to the global app variable
Here are explain well, in short:
http://www.hacksparrow.com/global-variables-in-node-js.html
So you are working with a set of Node modules, maybe a framework like Express.js, and suddenly feel the need to make some variables global. How do you make variables global in Node.js?
The most common advice to this one is to either "declare the variable without the var keyword" or "add the variable to the global object" or "add the variable to the GLOBAL object". Which one do you use?
First off, let's analyze the global object. Open a terminal, start a Node REPL (prompt).
> global.name
undefined
> global.name = 'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> delete global.name
true
> GLOBAL.name
undefined
> name = 'El Capitan'
'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> var name = 'Sparrow'
undefined
> global.name
'Sparrow'
My preferred way is to use circular dependencies*, which node supports
in app.js define var app = module.exports = express(); as your first order of business
Now any module required after the fact can var app = require('./app') to access it
app.js
var express = require('express');
var app = module.exports = express(); //now app.js can be required to bring app into any file
//some app/middleware, config, setup, etc, including app.use(app.router)
require('./routes'); //module.exports must be defined before this line
routes/index.js
var app = require('./app');
app.get('/', function(req, res, next) {
res.render('index');
});
//require in some other route files...each of which requires app independently
require('./user');
require('./blog');
this is pretty easy thing, but people's answers are confusing and complex at the same time.
let me show you how you can set global variable in your express app. So you can access it from any route as needed.
Let's say you want set a global variable from your main / route
router.get('/', (req, res, next) => {
req.app.locals.somethingNew = "Hi setting new global var";
});
So you'll get req.app from all the routes. and then you'll have to use the locals to set global data into. like above show you're all set. now
I will show you how to use that data
router.get('/register', (req, res, next) => {
console.log(req.app.locals.somethingNew);
});
Like above from register route you're accessing the data has been set earlier.
This is how you can get this thing working!
As others have already shared, app.set('config', config) is great for this. I just wanted to add something that I didn't see in existing answers that is quite important. A Node.js instance is shared across all requests, so while it may be very practical to share some config or router object globally, storing runtime data globally will be available across requests and users. Consider this very simple example:
var express = require('express');
var app = express();
app.get('/foo', function(req, res) {
app.set('message', "Welcome to foo!");
res.send(app.get('message'));
});
app.get('/bar', function(req, res) {
app.set('message', "Welcome to bar!");
// some long running async function
var foo = function() {
res.send(app.get('message'));
};
setTimeout(foo, 1000);
});
app.listen(3000);
If you visit /bar and another request hits /foo, your message will be "Welcome to foo!". This is a silly example, but it gets the point across.
There are some interesting points about this at Why do different node.js sessions share variables?.
const app = require('express')();
app.set('globalvar', "xyz");
app.get('globalvar');
I used app.all
The app.all() method is useful for mapping “global” logic for specific
path prefixes or arbitrary matches.
In my case, I'm using confit for configuration management,
app.all('*', function (req, res, next) {
confit(basedir).create(function (err, config) {
if (err) {
throw new Error('Failed to load configuration ', err);
}
app.set('config', config);
next();
});
});
In routes, you simply do req.app.get('config').get('cookie');
I solved the same problem, but I had to write more code.
I created a server.js file, that uses express to register routes.
It exposes a function,register , that can be used by other modules to register their own routes.
It also exposes a function, startServer , to start listening to a port
server.js
const express = require('express');
const app = express();
const register = (path,method,callback) => methodCalled(path, method, callback)
const methodCalled = (path, method, cb) => {
switch (method) {
case 'get':
app.get(path, (req, res) => cb(req, res))
break;
...
...
default:
console.log("there has been an error");
}
}
const startServer = (port) => app.listen(port, () => {console.log(`successfully started at ${port}`)})
module.exports = {
register,
startServer
}
In another module, use this file to create a route.
help.js
const app = require('../server');
const registerHelp = () => {
app.register('/help','get',(req, res) => {
res.send("This is the help section")
}),
app.register('/help','post',(req, res) => {
res.send("This is the help section")
})}
module.exports = {
registerHelp
}
In the main file, bootstrap both.
app.js
require('./server').startServer(7000)
require('./web/help').registerHelp()
John Gordon's answer was the first of dozens of half-explained / documented answers I tried, from many, many sites, that actually worked. Thank You Mr Gordon. Sorry I don't have the points to up-tick your answer.
I would like to add, for other newbies to node-route-file-splitting, that the use of the anonymous function for 'index' is what one will more often see, so using John's example for the main.js, the functionally-equivalent code one would normally find is:
app.get('/',(req, res) {
res.render('index', { title: 'Express' });
});

Resources