源码级别解析 · express.js, application.js, router/index.js
2026-03-15 | 每日技术深度解读
Express 是 Node.js 最流行的 Web 框架,核心特性是中间件流水线机制
核心机制:每个中间件调用 next() 将控制权传递给下一个中间件
app - Express 应用实例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);
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
app.init();
return app;
}
1. 创建 app 函数
app 本身是一个函数,接收 (req, res, next) 参数
2. 混入原型方法
使用 merge-descriptors 将 EventEmitter 和 application 原型方法混入 app
3. 创建 request/response 对象
基于原型创建,并绑定 app 引用
4. 初始化应用
调用 app.init() 初始化缓存、设置等
app.use = function use(fn) {
var offset = 0;
var path = '/';
// 如果第一个参数是路径
if (typeof fn !== 'function') {
var arg = fn;
while (Array.isArray(arg) && arg.length !== 0) {
arg = arg[0];
}
// 第一个参数是路径
if (typeof arg !== 'function') {
offset = 1;
path = fn;
}
}
var fns = flatten(slice.call(arguments, offset));
// 创建 Layer 对象
var layer = new Layer(path, {
sensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing'),
end: false
}, fn);
// 添加到 stack
this.stack.push(layer);
return this;
};
app.handle = function handle(req, res, callback) {
var router = this._router;
// 如果没有路由器,直接结束
if (!router) {
debug('no routes defined on app');
callback || callback = finalhandler(req, res);
return callback();
}
// 调用路由器的 handle 方法
router.handle(req, res, callback);
};
核心:app.handle 将请求转发给路由器处理
proto.handle = function handle(req, res, out) {
var self = this;
var stack = this.stack;
var idx = 0;
// next() 函数
function next(err) {
// 如果没有更多中间件
if (idx >= stack.length) {
setImmediate(out, err);
return;
}
var layer = stack[idx++];
var path = getPathname(req);
// 路径匹配
if (!layer.match(path)) {
return next(err);
}
// 执行中间件
var fn = layer.handle;
try {
fn(req, res, next);
} catch (err) {
next(err);
}
}
next(); // 开始执行
};
function Layer(path, options, fn) {
this.handle = fn;
this.name = fn.name || '<anonymous>';
this.params = undefined;
this.path = undefined;
this.regexp = pathRegexp(path, {
sensitive: options.sensitive,
strict: options.strict,
end: options.end
});
}
Layer.prototype.match = function match(path) {
// 使用正则匹配路径
var match = this.regexp.exec(path);
if (!match) {
return false;
}
// 提取参数
this.params = {};
this.path = match[0];
return true;
};
next() 是中间件流水线的核心
错误处理:如果中间件抛出异常或调用 next(err),Express 会跳过后续中间件,直接调用错误处理中间件
// 错误处理中间件必须有 4 个参数
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
识别方式:Express 通过函数参数数量(4 个)识别错误处理中间件
路径匹配流程:
示例:/users/:id → 匹配 /users/123 → req.params.id = '123'
var req = Object.create(http.IncomingMessage.prototype);
// 扩展属性
req.get = function(name) {
var lc = name.toLowerCase();
switch (lc) {
case 'referer':
case 'referrer':
return this.headers.referrer || this.headers.referer;
default:
return this.headers[lc];
}
};
req.param = function(name, defaultValue) {
var params = this.params || {};
var body = this.body || {};
var query = this.query || {};
if (params[name] != null) return params[name];
if (body[name] != null) return body[name];
if (query[name] != null) return query[name];
return defaultValue;
};
var res = Object.create(http.ServerResponse.prototype);
res.json = function json(obj) {
var val = obj;
// 允许设置内容类型
if (!this.get('Content-Type')) {
this.set('Content-Type', 'application/json');
}
// 发送 JSON 响应
return this.send(JSON.stringify(val));
};
res.send = function send(body) {
var chunk = body;
// 根据内容类型处理
switch (typeof chunk) {
case 'string':
if (!this.get('Content-Type')) {
this.type('html');
}
break;
case 'boolean':
case 'number':
case 'object':
return this.json(chunk);
}
// 发送响应
this.end(chunk);
return this;
};
methods.forEach(function(method){
app[method] = function(path){
if (method === 'get' && arguments.length === 1) {
// app.get('setting') 获取配置
return this.set(path);
}
// 创建路由
var route = this.route(path);
// 调用路由方法
route[method].apply(route, slice.call(arguments, 1));
return this;
};
});
// app.route() 实现
app.route = function route(path) {
var route = new Route(path);
var layer = new Layer(path, {
sensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing'),
end: true
}, route.dispatch.bind(route));
layer.route = route;
this.stack.push(layer);
return route;
};
区别:Router.stack 存储全局中间件,Route.stack 存储特定路由的中间件
Route.prototype.dispatch = function dispatch(req, res, done) {
var idx = 0;
var stack = this.stack;
var method = req.method.toLowerCase();
function next(err) {
// 如果有错误或已处理完所有中间件
if (err && err === 'route') {
return done();
}
if (err) {
return done(err);
}
if (idx >= stack.length) {
return done();
}
var layer = stack[idx++];
// 检查方法是否匹配
if (layer.method && layer.method !== method) {
return next(err);
}
// 执行中间件
try {
layer.handle_request(req, res, next);
} catch (err) {
next(err);
}
}
next();
};
app.param = function param(name, fn) {
// 参数处理中间件映射
(this.params[name] = this.params[name] || []).push(fn);
return this;
};
// 使用示例
app.param('userId', function(req, res, next, id) {
User.findById(id, function(err, user) {
if (err) return next(err);
if (!user) return next(new Error('User not found'));
req.user = user;
next();
});
});
app.get('/users/:userId', function(req, res) {
res.json(req.user); // req.user 已通过 param 中间件加载
});
| 类型 | 用途 | 示例 |
|---|---|---|
| 应用级中间件 | 全局处理 | app.use(logger) |
| 路由级中间件 | 特定路由 | router.use(auth) |
| 错误处理中间件 | 错误捕获 | app.use(errHandler) |
| 内置中间件 | 静态文件 | express.static() |
| 第三方中间件 | 扩展功能 | cors(), helmet() |
// ❌ 错误示例:异步错误无法捕获
app.use(async (req, res, next) => {
const data = await fetchData(); // 如果这里出错
next(); // 错误不会被捕获
});
// ✅ 正确示例:包装异步错误
app.use(async (req, res, next) => {
try {
const data = await fetchData();
next();
} catch (err) {
next(err); // 传递给错误处理中间件
}
});
// ✅ 更好的方式:使用 express-async-handler
const asyncHandler = require('express-async-handler');
app.use(asyncHandler(async (req, res, next) => {
const data = await fetchData(); // 自动捕获错误
next();
}));
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.path} - ${res.statusCode} - ${duration}ms`);
});
next();
});
原理:监听 response 的 'finish' 事件,计算请求处理时间
app.use((req, res, next) => {
// 设置安全头
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
// 防止点击劫持
res.removeHeader('X-Powered-By');
next();
});
推荐:使用 helmet() 中间件自动设置安全头
function logger(format) {
format = format || ':method :url :status';
return function(req, res, next) {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
const log = format
.replace(':method', req.method)
.replace(':url', req.url)
.replace(':status', res.statusCode)
.replace(':duration', duration + 'ms');
console.log(log);
});
next();
};
}
app.use(logger(':method :url :status - :duration'));
const assert = require('assert');
const request = require('supertest');
const app = express();
// 测试中间件
function testMiddleware(req, res, next) {
req.testProperty = 'test-value';
next();
}
describe('测试中间件', () => {
it('应该设置 testProperty', (done) => {
request(app.use(testMiddleware))
.get('/')
.expect((res) => {
assert.equal(res.req.testProperty, 'test-value');
})
.end(done);
});
});
// 组合多个中间件
function compose(middlewares) {
return function(req, res, next) {
let index = -1;
function dispatch(i) {
if (i <= index) {
return next(new Error('next() called multiple times'));
}
index = i;
const fn = middlewares[i];
if (!fn) {
return next();
}
try {
fn(req, res, function next(err) {
if (err) {
return next(err);
}
dispatch(i + 1);
});
} catch (err) {
next(err);
}
}
dispatch(0);
};
}
选择建议:Express 适合快速开发,Koa 适合现代化项目
测试环境:Node.js v20, 单核 CPU, 1GB 内存
Express 5.0 带来的改进
Express 中间件就是责任链模式的实现
Express 应用的生命周期就是模板方法
app.init()app.use()app.get/post/...app.listen()app.handle()app.on('mount', function(parent) {
console.log('App mounted');
});
// EventEm
itter 继承
mixin(app, EventEmitter.prototype, false);
// 触发事件
app.emit('mount', parent);
app.emit('error', err);
应用场景:生命周期事件、错误事件、自定义事件
// 不同的认证策略
const strategies = {
jwt: jwtAuth,
session: sessionAuth,
basic: basicAuth
};
function authMiddleware(strategy) {
return function(req, res, next) {
const authFn = strategies[strategy];
if (!authFn) {
return next(new Error('Invalid auth strategy'));
}
authFn(req, res, next);
};
}
app.use(authMiddleware('jwt'));
// 装饰 request 对象
function decorateRequest(req, res, next) {
req.user = null;
req.isAuthenticated = function() {
return !!this.user;
};
req.login = function(user) {
this.user = user;
};
next();
}
app.use(decorateRequest);
// 后续中间件可以使用扩展方法
app.use((req, res, next) => {
if (req.isAuthenticated()) {
// ...
}
});
// 统一错误处理类
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
// 全局错误处理中间件
app.use((err, req, res, next) => {
err.statusCode = err.statusCode || 500;
err.status = err.status || 'error';
res.status(err.statusCode).json({
status: err.status,
message: err.message
});
});
const config = {
development: {
port: 3000,
db: 'mongodb://localhost/dev',
jwtSecret: 'dev-secret'
},
production: {
port: process.env.PORT || 8080,
db: process.env.DB_URL,
jwtSecret: process.env.JWT_SECRET
}
};
const env = process.env.NODE_ENV || 'development';
module.exports = config[env];
推荐:使用 dotenv 管理环境变量
GET /usersPOST /usersPUT /users/:idDELETE /users/:id{
"success": true,
"data": {},
"message": "OK"
}
// 启用调试日志
DEBUG=express:* node app.js
// 自定义调试
const debug = require('debug')('app:middleware');
app.use((req, res, next) => {
debug(`${req.method} ${req.url}`);
next();
});
调试模块:使用 debug 模块分类输出调试信息
10 大安全建议
body-parser - 请求体解析cors - 跨域支持helmet - 安全头morgan - 日志compression - 压缩Express 中间件流水线源码解读
从 createApplication 到 next() 链式调用
从 Layer 抽象到 Router 路由系统
完整拆解 Express 核心架构
访问更多技术文章:https://atcfu.com/ai-articles/