Pass variable to expressjs 3 routes - node.js

I have an ExpressJS 3 app and have my routes in a separate file. I'd like to declare some configs in my app.js that are available in the routes file - outside of the route definitions themselves.
In my app.js I would like to do something such as:
app.set('path_to_models', '/path/models/');
Then in my routes/index.js file I would like to be able to do this:
var Product = require(app.get('path_to_models') + 'product');
exports.list = function(req, res){
return Product.find(function (err, products) {
if (!err) {
res.render('product/manage', { products: products });
} else {
res.render('5xx');
}
});
};
I've seen a few posts related to this but none really addressed what I am looking for. I know that I can wrap the routes in a function but would like an alternative way that will keep my code as is if at all possible.

I just make a separate config module that holds my configuration and in any module that needs info from the config, I just require it as normal. Why drag express into the mix when a more loosely coupled approach works just fine.
config.js
exports.pathToModels = "/path/to/models";
routes.js
var config = require("./config");
console.log(config.pathToModels);

Simply pass app as an argument to `routes/index.js':
var routes = require('./routes/index.js')(app);
UPDATED: This should be
var routes = require('./routes/index.js').init(app);
and in routes/index.js:
var app;
exports=function(whichApp) {
UPDATED: This should be
exports.init=function(whichApp) {
app=whichApp;
// do initialization stuff
return exports;
}
exports.list=...

Related

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).

Express Routes in Parse Cloud Code Module

I am using parse.com cloud code with express to setup my routes. I have done this in the past with node, and I have my routes in separate files. So, in node I do
app.js
express = require("express");
app = exports.app = express();
require("./routes/js/account");
account.js
app = module.parent.exports.app;
app.get("/api/account/twitter", passport.authenticate("twitter"));
All the examples on parses site https://parse.com/docs/cloud_code_guide#webapp show this being done as follows.
app.js
var express = require('express');
var app = express();
app.get('/hello', function(req, res) {
res.render('hello', { message: 'Congrats, you just set up your app!' });
});
So, I would like to change the bottom to include a routes folder with separate routes files, but am not sure how to do this in parse.
I know this post is a little old, but I just wanted to post a solution for anyone still looking to get this to work.
What you need to do, is create your route file, I keep them in 'routes' forlder, for example <my_app_dir>/cloud/routes/user.js
Inside user.js you will have something that looks like this:
module.exports = function(app) {
app.get("/users/login", function(req, res) {
.. do your custom logic here ..
});
app.get("/users/logout", function(req, res) {
.. do your custom logic here ..
});
}
Then, in app.js you just include your file, but remember that you need to append cloud to the path, and pass the reference to your app instance:
require('cloud/routes/user')(app);
Also, remember that express evaluates routes in order, so you should take that into consideration when importing several route files.
I'm using a different method, have the routes in app.js, but you can probably include them in file if you prefer. Take a look at the example app,
anyblog on github
The way it works:
Set up a controller:
// Controller code in separate files.
var postsController = require('cloud/controllers/posts.js');
Add the controller route
// Show all posts on homepage
app.get('/', postsController.index);
// RESTful routes for the blog post object.
app.get('/posts', postsController.index);
app.get('/posts/new', postsController.new);
And then in posts.js, you can use exports, ex.
var Post = Parse.Object.extend('Post');
// Display all posts.
exports.index = function(req, res) {
var query = new Parse.Query(Post);
query.descending('createdAt');
query.find().then(function(results) {
res.render('posts/index', {
posts: results
});
},
function() {
res.send(500, 'Failed loading posts');
});
};
// Display a form for creating a new post.
exports.new = function(req, res) {
res.render('posts/new', {});
};
Pass the app reference to the post controller, and add the routes from there

Calling already defined routes in other routes in Express NodeJS

I am writing a web app in node.js using Express. I have defined a route as follows:
app.get("/firstService/:query", function(req,res){
//trivial example
var html = "<html><body></body></html>";
res.end(html)
});
How do I reuse that route from within express?
app.get("/secondService/:query", function(req,res){
var data = app.call("/firstService/"+query);
//do something with the data
res.end(data);
});
I couldn't find anything in the API documentation and would rather not use another library like "request" because that seems kludgey. I am trying to keep my app as modular as possible. Thoughts?
Thanks
Similar to what Gates said, but I would keep the function(req, res){} in your routes file. So I would do something like this instead:
routes.js
var myModule = require('myModule');
app.get("/firstService/:query", function(req,res){
var html = myModule.firstService(req.params.query);
res.end(html)
});
app.get("/secondService/:query", function(req,res){
var data = myModule.secondService(req.params.query);
res.end(data);
});
And then in your module have your logic split up like so:
myModule.js
var MyModule = function() {
var firstService= function(queryParam) {
var html = "<html><body></body></html>";
return html;
}
var secondService= function(queryParam) {
var data = firstService(queryParam);
// do something with the data
return data;
}
return {
firstService: firstService
,secondService: secondService
}
}();
module.exports = MyModule;
Can you simply break this out into another function, put it in a shared spot and go from there?
var queryHandler = require('special_query_handler');
// contains a method called firstService(req, res);
app.get('/firstService/:query', queryHandler.firstService);
// second app
app.get('/secondService/:query', queryHandler.secondService);
Honestly, this whole business of nesting the call back inside of the app.get(...) is not really a great practice. You end up with a giant file containing all of the core code.
What you really want is a file filled with app.get() and app.post() statements with all of the callback handlers living in different, better organized files.
If you have a lot of middleware on your route, you can benefit from spreading:
const router = express.Router();
const myMiddleware = [
authenticationMiddleware(),
validityCheckMiddleware(),
myActualRequestHandler
];
router.get( "/foo", ...myMiddleware );
router.get( "/v1/foo", ...myMiddleware );
You can use run-middleware module exactly for that
app.runMiddleware('/firstService/query',function(responseCode,body,headers){
// Your code here
})
More info:
Module page in Github & NPM;
Examples of use run-middleware module
Disclosure: I am the maintainer & first developer of this module.
I have used following way:
at userpage.js
router.createSitemap = function(req, res, callback) { code here callback(value); }
at product.js
var userPageRouter = require('userpages');
userPageRouter.createSitemap(req, res, function () {
//console.log('sitemap');
});
Also can use in same userpage.js router I can use for other routing as well. eg.
router.get('/sitemap', function (req, res, next) {
router.createSitemap(req, res, function () {
res.redirect('/sitemap.xml');
}); });
Hope this will help.

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' });
});

Using routes in Express-js

So I'm starting to use Node.js. I saw the video with Ryan Dahl on Nodejs.org and heard he recommended Express-js for websites.
I downloaded the latest version of Express, and began to code. I have a fully fledged static view up on /, but as soon as I try sending parameters, I get errors like this:
Cannot GET /wiki
I tried following the guide on expressjs.com but the way one uses routes has changed in the latest version, which makes the guide unusable.
Guide:
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if (id) {
// do something
} else {
next();
}
});
Generated by Express:
app.get('/', routes.index);
My problem arises when I try and add another route.
app.get('/wiki', routes.wiki_show);
I've tried a bunch of approaches, but I keep getting the Cannot GET /wiki (404) error.
routes/index.js looks like this:
exports.index = function(req, res) {
res.render('index', { title: 'Test', articles: articles, current_article: current_article, sections: sections })
};
The only thing I did there was add some parameters (arrays in the same file) and this i working. But when I copy the contents and change exports.index to exports.wiki or exports.wiki_show I still get the Cannot GET /wiki error.
Can anyone explain to me what I'm missing here? - Thanks.
So, after I created my question, I got this related list on the right with a similar issue: Organize routes in Node.js.
The answer in that post linked to the Express repo on GitHub and suggests to look at the 'route-separation' example.
This helped me change my code, and I now have it working. - Thanks for your comments.
My implementation ended up looking like this;
I require my routes in the app.js:
var express = require('express')
, site = require('./site')
, wiki = require('./wiki');
And I add my routes like this:
app.get('/', site.index);
app.get('/wiki/:id', wiki.show);
app.get('/wiki/:id/edit', wiki.edit);
I have two files called wiki.js and site.js in the root of my app, containing this:
exports.edit = function(req, res) {
var wiki_entry = req.params.id;
res.render('wiki/edit', {
title: 'Editing Wiki',
wiki: wiki_entry
})
}
The route-map express example matches url paths with objects which in turn matches http verbs with functions. This lays the routing out in a tree, which is concise and easy to read. The apps's entities are also written as objects with the functions as enclosed methods.
var express = require('../../lib/express')
, verbose = process.env.NODE_ENV != 'test'
, app = module.exports = express();
app.map = function(a, route){
route = route || '';
for (var key in a) {
switch (typeof a[key]) {
// { '/path': { ... }}
case 'object':
app.map(a[key], route + key);
break;
// get: function(){ ... }
case 'function':
if (verbose) console.log('%s %s', key, route);
app[key](route, a[key]);
break;
}
}
};
var users = {
list: function(req, res){
res.send('user list');
},
get: function(req, res){
res.send('user ' + req.params.uid);
},
del: function(req, res){
res.send('delete users');
}
};
var pets = {
list: function(req, res){
res.send('user ' + req.params.uid + '\'s pets');
},
del: function(req, res){
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
}
};
app.map({
'/users': {
get: users.list,
del: users.del,
'/:uid': {
get: users.get,
'/pets': {
get: pets.list,
'/:pid': {
del: pets.del
}
}
}
}
});
app.listen(3000);
Seems that only index.js get loaded when you require("./routes") .
I used the following code in index.js to load the rest of the routes:
var fs = require('fs')
, path = require('path');
fs.readdirSync(__dirname).forEach(function(file){
var route_fname = __dirname + '/' + file;
var route_name = path.basename(route_fname, '.js');
if(route_name !== 'index' && route_name[0] !== "."){
exports[route_name] = require(route_fname)[route_name];
}
});
You could also organise them into modules. So it would be something like.
./
controllers
index.js
indexController.js
app.js
and then in the indexController.js of the controllers export your controllers.
//indexController.js
module.exports = function(){
//do some set up
var self = {
indexAction : function (req,res){
//do your thing
}
return self;
};
then in index.js of controllers dir
exports.indexController = require("./indexController");
and finally in app.js
var controllers = require("./controllers");
app.get("/",controllers.indexController().indexAction);
I think this approach allows for clearer seperation and also you can configure your controllers by passing perhaps a db connection in.
No one should ever have to keep writing app.use('/someRoute', require('someFile')) until it forms a heap of code.
It just doesn't make sense at all to be spending time invoking/defining routings. Even if you do need custom control, it's probably only for some of the time, and for the most bit you want to be able to just create a standard file structure of routings and have a module do it automatically.
Try Route Magic
As you scale your app, the routing invocations will start to form a giant heap of code that serves no purpose. You want to do just 2 lines of code to handle all the app.use routing invocations with Route Magic like this:
const magic = require('express-routemagic')
magic.use(app, __dirname, '[your route directory]')
For those you want to handle manually, just don't use pass the directory to Magic.

Resources