Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
remove app.router and refactor middleware processing
This is an overhaul of middleware processing, Router and Route. Connect is no
longer used to process the middleware stack. This functionality has been
split into two parts: middleware stack and default error response.

The entry point for request processing is the `app.handle` method. It
sets up the default error response handle (to run in the event of no
other error handler) and then triggers the app router (instance of
Router) to handle the request.

The app router `handle` function contains the middleware dispatch layer
previously in the connect codebase. This layer handle the logic for
dispatching `.use` calls (stripping paths if needed). The app contains a
base router `app._router`. New routes can be created and `.use`d on this
router to organize routes into files.

Routers now have the following methods `.use`, `.all`, `.param` which
are all public.

Additionally, Routers have a `.route(path)` method which returns a new
instance of Route for the requested path. Route(s) are isolated
middleware stacks and contain methods for the HTTP verbs as well as an
`.all` method to act similar to middleware. These methods are chainable
to easily describe requirements for a route.

  var route = Router.route('/foo'); // or 'app.route('/foo')'

  route
  .all(auth)
  .get(function(...) {})
  .all(more_checks)
  .post(function(...) {})

Any Route and Router methods which accept handlers also accept error
(arity 4) handlers which will also behave as expected.

Finally, the `app.router` getter has been removed. Middleware and
handlers are run IN THE ORDER they are seen in the file. This means that
code which injected the `app.router` and then added error handlers (or
other middleware) will need to be updated to move those handlers after
any requests added on the app object. The examples have been updated
accordingly. This is the largest breaking change to codebases in this
commit.
  • Loading branch information
defunctzombie committed Feb 3, 2014
1 parent 4bf9cfd commit f41d09a
Show file tree
Hide file tree
Showing 15 changed files with 822 additions and 507 deletions.
6 changes: 6 additions & 0 deletions History.md
Expand Up @@ -6,14 +6,20 @@
- `req.accepted*` - use `req.accepts*()` instead
- `app.configure` - use logic in your own app code
- `express.createServer()` - it has been deprecated for a long time. Use `express()`
- `app.router` - is removed
* change:
- `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings`
- `req.params` is now an object instead of an array
- `json spaces` no longer enabled by default in development
- `res.locals` is no longer a function. It is a plain js object. Treat it as such.
- `app.route` -> `app.mountpath` when mounting an express app in another express app
* refactor:
- `req.accepts*` with [accepts](https://github.com/expressjs/accepts)
- `req.is` with [type-is](https://github.com/expressjs/type-is)
* add:
- `app.router()` - returns the app Router instance
- `app.route()` - Proxy to the app's `Router#route()` method to create a new route
- Router & Route - public API

3.4.7 / 2013-12-10
==================
Expand Down
60 changes: 27 additions & 33 deletions examples/error-pages/index.js
Expand Up @@ -25,14 +25,32 @@ app.use(express.favicon());

silent || app.use(express.logger('dev'));

// "app.router" positions our routes
// above the middleware defined below,
// this means that Express will attempt
// to match & call routes _before_ continuing
// on, at which point we assume it's a 404 because
// no route has handled the request.
// Routes

app.use(app.router);
app.get('/', function(req, res){
res.render('index.jade');
});

app.get('/404', function(req, res, next){
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});

app.get('/403', function(req, res, next){
// trigger a 403 error
var err = new Error('not allowed!');
err.status = 403;
next(err);
});

app.get('/500', function(req, res, next){
// trigger a generic (500) error
next(new Error('keyboard cat!'));
});

// Error handlers

// Since this is the last non-error-handling
// middleware use()d, we assume 404, as nothing else
Expand All @@ -44,7 +62,7 @@ app.use(app.router);

app.use(function(req, res, next){
res.status(404);

// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
Expand Down Expand Up @@ -81,32 +99,8 @@ app.use(function(err, req, res, next){
res.render('500', { error: err });
});

// Routes

app.get('/', function(req, res){
res.render('index.jade');
});

app.get('/404', function(req, res, next){
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});

app.get('/403', function(req, res, next){
// trigger a 403 error
var err = new Error('not allowed!');
err.status = 403;
next(err);
});

app.get('/500', function(req, res, next){
// trigger a generic (500) error
next(new Error('keyboard cat!'));
});

if (!module.parent) {
app.listen(3000);
silent || console.log('Express started on port 3000');
}
}
14 changes: 6 additions & 8 deletions examples/error/index.js
Expand Up @@ -8,13 +8,6 @@ var express = require('../../')
, test = app.get('env') == 'test';

if (!test) app.use(express.logger('dev'));
app.use(app.router);

// the error handler is strategically
// placed *below* the app.router; if it
// were above it would not receive errors
// from app.get() etc
app.use(error);

// error handling middleware have an arity of 4
// instead of the typical (req, res, next),
Expand Down Expand Up @@ -42,7 +35,12 @@ app.get('/next', function(req, res, next){
});
});

// the error handler is placed after routes
// if it were above it would not receive errors
// from app.get() etc
app.use(error);

if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
}
45 changes: 20 additions & 25 deletions examples/web-service/index.js
Expand Up @@ -40,29 +40,6 @@ app.use('/api', function(req, res, next){
next();
});

// position our routes above the error handling middleware,
// and below our API middleware, since we want the API validation
// to take place BEFORE our routes
app.use(app.router);

// middleware with an arity of 4 are considered
// error handling middleware. When you next(err)
// it will be passed through the defined middleware
// in order, but ONLY those with an arity of 4, ignoring
// regular middleware.
app.use(function(err, req, res, next){
// whatever you want here, feel free to populate
// properties on `err` to treat it differently in here.
res.send(err.status || 500, { error: err.message });
});

// our custom JSON 404 middleware. Since it's placed last
// it will be the last middleware called, if all others
// invoke next() and do not respond.
app.use(function(req, res){
res.send(404, { error: "Lame, can't find that" });
});

// map of valid api keys, typically mapped to
// account info with some sort of database like redis.
// api keys do _not_ serve as authentication, merely to
Expand Down Expand Up @@ -104,12 +81,30 @@ app.get('/api/repos', function(req, res, next){
app.get('/api/user/:name/repos', function(req, res, next){
var name = req.params.name
, user = userRepos[name];

if (user) res.send(user);
else next();
});

// middleware with an arity of 4 are considered
// error handling middleware. When you next(err)
// it will be passed through the defined middleware
// in order, but ONLY those with an arity of 4, ignoring
// regular middleware.
app.use(function(err, req, res, next){
// whatever you want here, feel free to populate
// properties on `err` to treat it differently in here.
res.send(err.status || 500, { error: err.message });
});

// our custom JSON 404 middleware. Since it's placed last
// it will be the last middleware called, if all others
// invoke next() and do not respond.
app.use(function(req, res){
res.send(404, { error: "Lame, can't find that" });
});

if (!module.parent) {
app.listen(3000);
console.log('Express server listening on port 3000');
}
}

0 comments on commit f41d09a

Please sign in to comment.