Reputation: 5406
So I've seen TJ's guide to creating modular Express-apps, followed it to good effects, but want to know more about the details of how it works, however a search gives me no answers.
In short I am wondering: When mounting apps in Express, what parts of the apps are shared and what parts are not?
Some examples to clarify my question:
app.js:
app.use(express.bodyParser());
app.use(loginApi); //loginApi is an express app
app.listen(3000);
This example works. But if I place the app.use(loginApi)
before app.use(express.bodyParser());
, the body parser will not be available in the loginApi subapp. Why is that?
Another example:
submodule.js
var app = module.exports = require('express')();
app.all('*', function(req, res, next){
console.log('nifty middleware');
next();
});
app.js
app.get('/funtimes', fn);
app.use(submodule);
app.listen(3000);
Now in this example, If I understand it correctly, the /funtimes
route will not be affected by the submodule middleware for all routes. But what about the rest of the routes of app.js ? Will they be affected? And what if I add another module, will it be affected?
Upvotes: 3
Views: 3905
Reputation: 11062
if I place the app.use(loginApi) before app.use(express.bodyParser()); , the body parser will not be available in the loginApi subapp. Why is that?
That's because of the way Express handles requests. Any incoming request starts at the top of the middleware stack, starting with app.use()
stack.
Middleware are simply functions that have the function signature function(req, res, next)
which either call next()
if they want to hand off the request to subsequent functions, or send a response themselves. You define a 'middleware chain' of a bunch of these functions (many are provided by express, like express.logger()
and express.compress()
.)
So in the following scenario:
app.use(express.bodyParser());
var loginApi = require('./api/index.js')
app.use(loginApi);
app.use(app.router);
then an incoming request will first hit app.use(express.bodyParser())
, parsing req.body
. Then that function calls its internal next()
, passing it to the next function in the middleware chain (app.use(loginApi)
). The loginApi app has its own middleware chain, but the requests already have req.body
set from the outer app. If the loginApi doesn't send a response, the request will continue to app.use(app.router)
and at that point the requests will go to the routing functions you set up in your outer app.
So the answer is: A mounted app will have the middleware functions shared, which are placed before the line app.use(loginApi)
Upvotes: 4
Reputation: 2206
What you're asking about is middleware. This confused me for a while. Middleware are the functions that run in order to take a request in and serve back a response. app.use() takes a function as its only argument. That function manipulates the request in a consistent way.
app.use is a lot like app.all("*").
The order matters. For example, you might want to run a validator before serving the response.
One thing I learned recently is that you can pass an array of middleware functions to a route. For example
app.get("/whatever",[
function(req,res,next}{
...validation...
next();
},
function(req,res) {
...actions....
res.send(200);
}
]);
The next callback tells express to run the next function in the middleware. Middleware can also modify the request object. This is used a lot in authentication. For example, you'll see req.user getting defined from the database so in later middleware you'll be able to refer to properties of the user. But, it can also be used for a ton of other stuff.
Upvotes: 2
Reputation: 887957
Middleware runs in order (until one of the middlewares doesn't call next()
).
If you use()
your mounted app before use()
ing bodyParser
, the entire sub-app will run before bodyParser
adds its properties.
Upvotes: 3