Routing Architecture
Express provides the public application and route APIs, while the lower-level routing implementation is supplied by the external router package. The application is callable as a request handler and forwards incoming work to app.handle.
This separation keeps Express focused on application integration: it mixes application behavior into the app, creates request and response prototypes, and initializes the application. Route matching itself is not shown in this repository excerpt; the visible boundary is the Router dependency.
Sources: lib/express.js:36-39, lib/express.js:19
Core concepts
External router
The external router is the component Express requires as Router; this is where the available evidence places the delegated routing implementation.
Sources: lib/express.js:19
Application router
The application router is the routing surface that application methods proxy into, including route creation and middleware registration. app.route(path) returns a Route through this.router.route(path).
Sources: lib/application.js:246-258
Route parameters
A route parameter is a dynamic path value exposed to handlers through req.params; the tests demonstrate handlers reading req.params.id after requests target paths containing :id.
The main integration points are:
| Symbol | Plain-language role | Evidence |
|---|---|---|
Router | External routing dependency required by Express | require('router') |
Route | Per-path route object returned by the application router | app.route(path) returns this.router.route(path) |
req | Request prototype mixed onto application requests | Object.create(req, ...) |
res | Response prototype mixed onto application responses | Object.create(res, ...) |
Sources: test/app.param.js:50-57, lib/express.js:19, lib/application.js:246-258, lib/express.js:44-52
How Express places the routing boundary
The module-level boundary is explicit: lib/express.js requires Router from the package named router, alongside Express’s request and response modules.
The application factory creates a callable app function. When Node invokes that function with req, res, and next, it calls app.handle(req, res, next).
function createApplication() {
var app = function(req, res, next) {
app.handle(req, res, next);
};
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false);The important detail is that request dispatch enters through app.handle, while the application’s methods come from proto, which is required from ./application.
Evidence
- express-modulelib/express.js:19
- express-modulelib/express.js:20
- express-modulelib/express.js:21
- application-factorylib/express.js:36
- external-routerlib/express.js:19
- request-prototypelib/express.js:20
- response-prototypelib/express.js:21
Sources: lib/express.js:19, lib/express.js:20, lib/express.js:21, lib/express.js:36-56, lib/express.js:18
How routes are registered and delegated
Application HTTP-method helpers turn a path into a route by calling this.route(path), then applying the method-specific arguments to that route. This means registration is expressed through the application API but delegated to a Route object.
app.all(path) follows the same shape, except it applies the supplied handlers to every method listed in methods.
The application’s use API is likewise described as a proxy to Router#use(). The source specifically says that an Express app passed as the function is mounted at the route specified.
That is the repository’s visible guarantee for nested routers: mounting is handed to the router layer at the chosen route. The supplied excerpts do not include the external package’s path-rewrite implementation, so they do not establish the exact value of a nested route’s internal path or whether a particular request property is temporarily changed during dispatch.
Evidence
- application-methodlib/application.js:471
- route-factorylib/application.js:478
- route-objectlib/application.js:478
- method-handlerlib/application.js:478
Sources: lib/application.js:471-481, lib/application.js:484-503, lib/application.js:180-190
How dynamic parameters reach handlers
A dynamic segment is written into a route pattern with a colon name, such as /user/:id. The test then reads req.params.id inside the handler and verifies that the request /user/123 produces the value 123.
Parameter processing can also be customized through app.param. The shown callback converts the incoming id to a number, writes it back to req.params.id, and calls next; invalid numeric input skips the route with next('route').
The router tests also show ordinary middleware sequencing: fn1 increments a counter and calls next(), followed by fn2, which increments the counter again and calls next().
Evidence
- applicationlib/express.js:36
- dispatchlib/express.js:36
- initializerlib/express.js:36
- requestlib/express.js:36
Sources: test/app.param.js:50-57, test/app.param.js:43-47, test/Router.js:481-484, test/Router.js:486-489
How it connects
Application route registration connects to the broader dispatch surface described in App Routing & Request Dispatch, where app.use, app.route, app.all, and app.handle are explained together.
The request and response prototypes created during application construction connect to The Request Object and Response: Sending Data.
Examples of parameterized resources connect to Examples: Getting Started and Examples: MVC & Route Organization. The resource example defines :id, :a, :b, and :format patterns and reads their values from req.params.
Sources: lib/application.js:180-190, lib/application.js:246-258, lib/application.js:484-503, lib/express.js:44-52, examples/resource/index.js:13-24
Key takeaways
- Express requires the external
routerpackage asRouter. appreceives requests and enters dispatch through app.handle.- Application methods create routes through
this.route(path). - app.use delegates mounting to
Router#use()at the specified route. - Dynamic segments are exposed to handlers through req.params; app.param can transform them.