I know I can get the Express app from inside an individual route with:
req.app
However I need to start a single instance of a module inside routes/index.js, i.e.:
var myModule = require('my-module')(propertyOfApp)
How can I get the express app from the router?
It really depends on your own implementation, but what I suggested in the comments should be working:
// index.js
module.exports = function(app) {
// can use app here
// somehow create your router and do the magic, configure it as you wish
router.get('/path', function (req, res, next) {});
return router;
}
// app.js
// actually call the function that is returned by require,
// and when executed, the function will return your configured router
app.use(require('./index')(app));
p.s.
Of course this is just a sample - you can configure your router with path, and all kind of properties you wish. Cheers! :)
Related
I was learning Express in Node.js and came across Router() allowing us to modularize our routes. But than I found this code:
// we'll create our routes here
// get an instance of router
var router = express.Router();
...
// route with parameters (http://localhost:8080/hello/:name)
router.get('/hello/:name', function(req, res) {
res.send('hello ' + req.params.name + '!');
});
// apply the routes to our application
app.use('/', router);
What confused me is that why we need to use app.use('/', router); to apply the routes. That is, what if we use app.get('/', router);
I am giving you a simple code example to make you understand the use of express.Router(). Yes you are right that it helps in modularization. Actually it makes our main app.js file clean from all the routes. We just put all those routes based on their purposes in different files and require them when needed.
so suppose I have two files app.js and register.js
// app.js file's code goes here
let express = require("express")
let app = express()
let register = require("./routes/register")
app.use(register) // This will tell your app to import all those routes which are in register
// register.js file's code goes here
let express = require("express")
let router = express.Router()
router.get("/register", callback_function);
router.post("/register", callback_function);
module.exports = router;
So basically what I am trying to show is your register.js can contain all types of HTTP requests(GET, POST, PUT,...) and when we use app.use(register) this will handle all those routes. app.get("route_path", callback_function) is only for handling get requests to that path.
Router is just a middleware of it's own. If you use app.get('/', router) you will use the router just for GET requests. Using use channels all requests there.
When app.use is used then it handled all the HTTP methods, but when app.get is used it takes just GET method.
Added advantage to app.use is that route will match any path that follows its path immediately with a /.
For example:
app.use('/v1', ...)
will match /users, /users/accounts, /users/accounts/account-id, and so on.
I have a middleware, I call it like this:
app.use(example({optiona:'abc'}));
I want to access the app from the middleware function, and do another app.use, something like this:
module.exports = function (options){
app.use(...);
return function(req, res, next)
next();
}
I know the option to pass the app to the exports, but I want to do it without the option to pass it, or set it as global..
You could try looking into Express Routers as an option (read all about it).
Essentially, you could keep your first piece the same:
app.use(example({optiona:'abc'}));
And then you can do the following in the function instead:
var express = require("express");
var router = express.Router();
module.exports = function(options) {
// You can declare middleware specific to this router
router.use(...);
// You can declare routes specific to this router
router.get("/foo", ...);
router.all("/bar", ...);
// Then just return the router at the end
return router;
}
Routers allow you to set up "sub applications" with their own routes/middleware accordingly.
Node Express's Routing guide gives the following example for creating routes as modules:
/birds.js:
var express = require('express')
var router = express.Router()
// middleware that is specific to this router
router.use(function timeLog (req, res, next) {
console.log('Time: ', Date.now())
next()
})
// define the home page route
router.get('/', function (req, res) {
res.send('Birds home page')
})
// define the about route
router.get('/about', function (req, res) {
res.send('About birds')
})
module.exports = router
/app.js:
var birds = require('./birds')
// ...
app.use('/birds', birds)
I want to know why they put the first two lines of birds.js there instead of in app.js.
Firstly, app.js calls a method of app. How is app supposed to be defined within app.js? I take it they (oddly) neglected to include that necessary code for the sake of the tutorial.
Secondly, say I wanted a second route as a module, for dogs as well as birds, in a file called dogs.js. Could it look identical to birds.js WRT the first two lines? AFAIK that would result in two instances of express. (Or three if it's needed in app.js as well?!)
The example is not complete. The whole app setup is left out (i asume because it is explained further up in the docs anyway and replaced with // ...). In your app.js you need at least:
var express = require('express');
var app = express();
The first 2 lines in bird.js have nothing to do with the two (missing) lines in app.js. You need them to create a router.
And regarding your last question: Yes, you would create another router exactly like the bird router. A router is not an express app/instance and it's totally fine to have multiple of them in you app.
In the chain of calls inside Express middleware, do the app.param methods always get called before app.use?
I tested with this program changing the order of app.use vs app.param with express 4.10.2. The param always runs first, which makes sense because the route handler expects to be able to do req.params.foo and in order for that to work the param handlers need to have run.
var express = require('express');
var app = express();
app.use("/:file", function (req, res) {
console.log("#bug route", req.params.file);
res.send();
});
app.param("file", function (req, res, next, val) {
console.log("#bug param", val);
next();
});
app.listen(3003);
Run this and test with curl localhost:3003/foo and you get the output:
#bug param foo
#bug route foo
You can test it through logging, but I'm reasonably certain that in 4.0, everything is called in the order it's declared when you set up your app.
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