The app object is instantiated on creation of the Express server. It has a middleware stack that can be customized in app.configure()
(this is now deprecated in version 4.x).
To setup your middleware, you can invoke app.use(<specific_middleware_layer_here>)
for every middleware layer that you want to add (it can be generic to all paths, or triggered only on specific path(s) your server handles), and it will add onto your Express middleware stack. Middleware layers can be added one by one in multiple invocations of use
, or even all at once in series with one invocation.
See use
documentation for more details.
To give an example for conceptual understanding of Express Middleware, here is what my app middleware stack (app.stack) looks like when logging my app object to the console as JSON:
stack:
[ { route: '', handle: [Function] },
{ route: '', handle: [Function: static] },
{ route: '', handle: [Function: bodyParser] },
{ route: '', handle: [Function: cookieParser] },
{ route: '', handle: [Function: session] },
{ route: '', handle: [Function: methodOverride] },
{ route: '', handle: [Function] },
{ route: '', handle: [Function] } ]
As you might be able to deduce, I called app.use(express.bodyParser())
, app.use(express.cookieParser())
, etc, which added these express middleware 'layers' to the middleware stack. Notice that the routes are blank, meaning that when I added those middleware layers I specified that they be triggered on any route. If I added a custom middleware layer that only triggered on the path /user/:id
that would be reflected as a string in the route
field of that middleware layer object in the stack printout above.
Each layer is essentially adding a function that specifically handles something to your flow through the middleware.
E.g. by adding bodyParser
, you're ensuring your server handles incoming requests through the express middleware. So, now parsing the body of incoming requests is part of the procedure that your middleware takes when handling incoming requests -- all because you called app.use(bodyParser)
.
app.use()
is intended for binding middleware to your application. The path
is a "mount" or "prefix" path and limits the middleware to only apply to any paths requested that begin with it. It can even be used to embed another application:
// subapp.js
var express = require('express');
var app = modules.exports = express();
// ...
// server.js
var express = require('express');
var app = express();
app.use('/subapp', require('./subapp'));
// ...
By specifying /
as a "mount" path, app.use()
will respond to any path that starts with /
, which are all of them and regardless of HTTP verb used:
GET /
PUT /foo
POST /foo/bar
- etc.
app.get()
, on the other hand, is part of Express' application routing and is intended for matching and handling a specific route when requested with the GET
HTTP verb:
And, the equivalent routing for your example of app.use()
would actually be:
app.all(/^\/.*/, function (req, res) {
res.send('Hello');
});
(Update: Attempting to better demonstrate the differences.)
The routing methods, including app.get()
, are convenience methods that help you align responses to requests more precisely. They also add in support for features like parameters and next('route')
.
Within each app.get()
is a call to app.use()
, so you can certainly do all of this with app.use()
directly. But, doing so will often require (probably unnecessarily) reimplementing various amounts of boilerplate code.
Examples:
For simple, static routes:
app.get('/', function (req, res) {
// ...
});
vs.
app.use('/', function (req, res, next) {
if (req.method !== 'GET' || req.url !== '/')
return next();
// ...
});
With multiple handlers for the same route:
app.get('/', authorize('ADMIN'), function (req, res) {
// ...
});
vs.
const authorizeAdmin = authorize('ADMIN');
app.use('/', function (req, res, next) {
if (req.method !== 'GET' || req.url !== '/')
return next();
authorizeAdmin(req, res, function (err) {
if (err) return next(err);
// ...
});
});
With parameters:
app.get('/item/:id', function (req, res) {
let id = req.params.id;
// ...
});
vs.
const pathToRegExp = require('path-to-regexp');
function prepareParams(matches, pathKeys, previousParams) {
var params = previousParams || {};
// TODO: support repeating keys...
matches.slice(1).forEach(function (segment, index) {
let { name } = pathKeys[index];
params[name] = segment;
});
return params;
}
const itemIdKeys = [];
const itemIdPattern = pathToRegExp('/item/:id', itemIdKeys);
app.use('/', function (req, res, next) {
if (req.method !== 'GET') return next();
var urlMatch = itemIdPattern.exec(req.url);
if (!urlMatch) return next();
if (itemIdKeys && itemIdKeys.length)
req.params = prepareParams(urlMatch, itemIdKeys, req.params);
let id = req.params.id;
// ...
});
Note: Express' implementation of these features are contained in its Router
, Layer
, and Route
.
Best Answer
router.get
is only for defining subpaths. Consider this example:smaller
function will get called.bigger
function will get called.In short,
app.use('/first', router)
mounts the middleware at path /first, thenrouter.get
sets the subpath accordingly.But if we instead use the following:
fun
will get called,bigger
will get calledsmaller
will get calledBut remember for /first/sud, no function will get called.
This link may also help: http://expressjs.com/api.html#router