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).
Related
I am new to NodeJS. So I am writing NodeJS application with socket.io.
I understand how to separate controllers. In my app I created:
controllers/userCtrl.js
controller/marketCtrl.js etc.
And in userCtrl.js controller I did like this:
exports.create = function(req, res) {
// Create user
}
// Other actions
In application I use it:
// ...
var userCtrl = require('./controllers/userCtrl');
app.post('/user', userCtrl.create);
// ...
With models the same. But I have a lot of socket.io related code in app.js and don't understand how remove it (like controllers) from app.js:
var frontend = io.of('/frontend');
frontend.on('connection', function (client) {
logger.info('Someone connected to frontend socket');
client.on('join', function (message) {
logger.info('In join event');
var token = message.token;
if (!token) {
logger.debug('No usertoken provided. Sending login required');
client.emit('join', {error: 103, message: 'Login required', data: null});
return;
}
//... etc..
My question is: How to split socket.io related code into files? What is best practice for it? Thank you!
Different files is still the way. Use exports or module.exports and then just require in your app.js.
Perhaps make a setup() function that takes in an app/http instance, or whatever else you need in your socket.io stuff, and then call that function at the right time in app.js.
-- socketSetup.js --
'use strict';
var io = require('socket.io');
function setup( app, logger, whatever ){
//do stuff here
}
module.exports = setup;
-- app.js --
'use strict';
var express = require('express');
var socketSetup = require('./socketSetup.js');
var app = express();
//other express things
//setup the socket stuff
socketSetup( app, logger );
The result is a shorter and more readable app.js file, and your socket setup is contained as well. Repeat as things grow in your socketSetup.js file as well.
I'm making a nodeJS module, and I want to use expressJS as a framework for it.
I'm trying to see, how I could go by, including a function inside and app.get(); and call it via another file, such as the actual app.
var express = require("express");
var app = express();
app.get("/", function (req, res) {
exports.type = function (text) {
console.log(req.ip);
console.log(text);
}
});
now when I use this, and i call it on the actual app like:
var web = require("directory_to_file");
var express = require("express");
var app = express();
var http = require("http").Server(app);
app.get("/", function (req, res) {
web.type("Hello, world");
});
http.listen(10022, function () {
console.log("server is up");
});
I get an error:
TypeError: Property 'type' of object #<Object> is not a function
anyone know a way to make it so I can call the function?
There are generally two things you want to export as a module - an API and a Middleware. The classic example of middleware is an authentication module. To do the middleware, just export the middleware. I tend to do a little more than that so I can configure the middleware later. Something along the lines of this:
module.exports = exports = function(config) {
// Do something with config here
return function(req, res, next) {
// your middleware here
};
};
You can then use your middleware in your main program like this:
var app = require('express')(),
mymodule = require('./mymodule');
var config = {}; // replace with whatever config you need
app.use(mymodule(config));
app.listen(process.env.PORT || 3000);
To implement an API, you will create a Router object, then attach your routes to the Router object. You can then "mount" your router in your main program. For example, you could have a file called 'myroutes.js' with the following contents:
var express = require('express'),
myroutes = express.Router();
myroutes.get('/foo', (req, res) => {
res.status(200).type('application/json').send({ myparam: 'foo' });
});
module.exports = exports = myroutes;
Have the following in your main program:
var app = require('express')(),
myroutes = require('./myroutes');
app.use('/api', require('./myroutes'));
app.listen(process.env.PORT || 3000);
Here, in 'myroutes.js', I'm defining a sub-route of /foo and then in the main program, I'm mounting that on /api - so I would access /api/foo to access that API.
In your directory_to_file you are only exporting on app.get('/') which will never be called.
You could add in your directory_to_file the following code
var express = require('express');
var router = express.Router();
router.get('/', function(req, server) {
console.log(req.ip);
});
module.exports = router;
And in your main file you could use app.use('/', web)
A short explanation:
You are creating a new express app / config in your directory_to_file file which won't be launched or used. So your app.get event won't be fired once.
That's why web.type is not a function. You are not exporting anything.
Use the way I provided. This is a commonly used method.
You could call the code I provided a "route". Create multiple routes / route files and include them in your main method.
Your code just looks confused. If I understand you correctly, what you are really trying to do (at least in Node/express terminology) is write your own middleware.
Express is designed with this in mind and it's pretty straightforward e.g.
ipLogger.js
module.exports = function(req, res, next) {
console.log(req.ip);
next();
}
app.js
var http = require("http")
, express = require("express");
, app = express()
, server = http.Server(app)
, ipLogger = require("./ipLogger.js");
app.use(ipLogger()); // log IP of all requests
// handle routes
server.listen(10022, function() {
console.log("server is up");
});
Say I have some routes (I have a lot more, but this should explain):
router.post('/post');
router.get('/post/:id');
router.get('/posts/:page?');
router.get('/search');
For the /post ones I know I could do something like
app.use('/post', postRoutes)
Where postRoutes is the actual post routes in another file. However, I'd like to group all post related routes into a postRoutes component (so /post and /posts), search into a search component and so on. Is there a way to do something like
router.use(postRoutes); // includes routes 1-3 above
router.use(searchRoutes); // only the 4th route above
And so on? That would let me keep the top level file much cleaner.
Yes it is simple. You can even make more nesting levels. I think it is good to separate routes, especially when you have dozens of routes.
in your first file (server.js)
app.use(require("./allpost"));
app.use(require("./allqueries"));
in allpost.js
var express = require('express');
var router = new express.Router();
router.post('/post', function (req, res) {
//your code
});
router.get('/post/:id', function (req, res) {
//your code
});
router.get('/posts/:page?', function (req, res) {
//your code
});
when you want more nesting
router.use(require("./deeper"));
or when you want use path part
router.use("/post2/", require("./messages/private"));
module.exports = router;
You could do that by creating a special route file. Here's an example of such file
module.exports = (function() {
var express = require('express');
var router = express.Router();
router.get("/:id", function (request, response, next) {
request.body.id = request.params["id"];
// Do something ...
});
router.post("/someRoute", function (request, response, next) {
// Do something ...
});
// And so on ...
return router;
})();
Next, in you server.js file, include it like this
app.use('/post', require('./routes/postRoutes'));
The problem was I was thinking about this wrong. First off, don't use singular and plural. It makes it a headache and also makes it hard for people to remember the API.
Once I used all plural I had a setup like this in my index.js file:
// The API routes all start with /api and we pass app here so we can have some
// sub routes inside of api
app.use('/api', require('./app/api')(app));
And then in my api/index.js
var express = require('express');
var router = express.Router({ mergeParams: true });
var routeInit = function (app) {
app.use('sessions', require('./sessions')(router));
app.use('users', require('./users')(router));
return router;
};
module.exports = routeInit;
You can see that I'm passing the router manually each time. Then finally:
var routeInit = function (router) {
router.post('/blah', function (req, res, next) {
// Do stuff
});
return router;
};
module.exports = routeInit;
This allowed me to nest routes infinitely deep.
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
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' });
});