中间件系统
Vafast 的中间件系统是框架的核心功能之一,它允许您在请求处理过程中执行自定义逻辑。中间件可以用于身份验证、日志记录、错误处理、数据转换等。
什么是中间件?
中间件是一个函数,它在请求到达路由处理函数之前或之后执行。中间件可以:
- 修改请求对象
- 验证请求数据
- 记录请求信息
- 处理错误
- 添加响应头
- 执行任何自定义逻辑
中间件定义
基本中间件
typescript
const logMiddleware = async (req: Request, next: () => Promise<Response>) => {
const start = Date.now()
const response = await next()
const duration = Date.now() - start
console.log(`${req.method} ${req.url} - ${response.status} - ${duration}ms`)
return response
}中间件类型
typescript
type Middleware = (req: Request, next: () => Promise<Response>) => Promise<Response>中间件执行顺序
中间件按照数组中的顺序执行,形成一个执行链:
typescript
const routes = defineRoutes([
{
method: 'GET',
path: '/admin',
middleware: [authMiddleware, logMiddleware, rateLimitMiddleware],
handler: createHandler(() => 'Admin panel')
}
])执行顺序:
authMiddleware- 身份验证logMiddleware- 日志记录rateLimitMiddleware- 速率限制- 路由处理函数 - 实际业务逻辑
常用中间件示例
1. 日志中间件
typescript
const logMiddleware = async (req: Request, next: () => Promise<Response>) => {
const start = Date.now()
const method = req.method
const url = req.url
const userAgent = req.headers.get('user-agent')
console.log(`[${new Date().toISOString()}] ${method} ${url} - ${userAgent}`)
const response = await next()
const duration = Date.now() - start
console.log(`[${new Date().toISOString()}] ${method} ${url} - ${response.status} - ${duration}ms`)
return response
}2. 身份验证中间件
typescript
const authMiddleware = async (req: Request, next: () => Promise<Response>) => {
const authHeader = req.headers.get('authorization')
if (!authHeader) {
return new Response('Unauthorized', {
status: 401,
headers: { 'WWW-Authenticate': 'Bearer' }
})
}
const token = authHeader.replace('Bearer ', '')
try {
// 验证 token
const user = await validateToken(token)
// 将用户信息添加到请求中
;(req as any).user = user
return await next()
} catch (error) {
return new Response('Invalid token', { status: 401 })
}
}
// 使用示例
const routes = defineRoutes([
{
method: 'GET',
path: '/profile',
middleware: [authMiddleware],
handler: createHandler(({ req }) => {
const user = (req as any).user
return `Hello ${user.name}`
})
}
])3. CORS 中间件
typescript
const corsMiddleware = async (req: Request, next: () => Promise<Response>) => {
const response = await next()
// 添加 CORS 头
response.headers.set('Access-Control-Allow-Origin', '*')
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
return response
}4. 速率限制中间件
typescript
const rateLimitMap = new Map<string, { count: number; resetTime: number }>()
const rateLimitMiddleware = async (req: Request, next: () => Promise<Response>) => {
const ip = req.headers.get('x-forwarded-for') || 'unknown'
const now = Date.now()
const windowMs = 15 * 60 * 1000 // 15 分钟
const maxRequests = 100
const key = `${ip}:${Math.floor(now / windowMs)}`
const current = rateLimitMap.get(key)
if (current && current.resetTime > now) {
if (current.count >= maxRequests) {
return new Response('Too many requests', {
status: 429,
headers: { 'Retry-After': '900' }
})
}
current.count++
} else {
rateLimitMap.set(key, { count: 1, resetTime: now + windowMs })
}
return next()
}5. 错误处理中间件
typescript
const errorHandler = async (req: Request, next: () => Promise<Response>) => {
try {
return await next()
} catch (error) {
console.error('Error in route:', error)
if (error instanceof Error) {
return new Response(error.message, { status: 500 })
}
return new Response('Internal Server Error', { status: 500 })
}
}6. 数据验证中间件
typescript
const validateBody = (schema: any) => {
return async (req: Request, next: () => Promise<Response>) => {
try {
const body = await req.json()
// 这里可以使用任何验证库,如 Zod、Joi 等
const validationResult = validateSchema(schema, body)
if (!validationResult.valid) {
return new Response(JSON.stringify({
error: 'Validation failed',
details: validationResult.errors
}), {
status: 400,
headers: { 'Content-Type': 'application/json' }
})
}
// 将验证后的数据添加到请求中
;(req as any).validatedBody = validationResult.data
return next()
} catch (error) {
return new Response('Invalid JSON', { status: 400 })
}
}
}
// 使用示例
const userSchema = {
name: { type: 'string', required: true, minLength: 2 },
email: { type: 'string', required: true, format: 'email' },
age: { type: 'number', min: 18 }
}
const routes = defineRoutes([
{
method: 'POST',
path: '/users',
middleware: [validateBody(userSchema)],
handler: createHandler(({ req }) => {
const userData = (req as any).validatedBody
// 处理验证后的数据...
return new Response('User created', { status: 201 })
})
}
])中间件组合
创建中间件组合器
typescript
const combineMiddleware = (...middlewares: any[]) => {
return async (req: Request, next: () => Promise<Response>) => {
let index = 0
const executeNext = async (): Promise<Response> => {
if (index >= middlewares.length) {
return next()
}
const middleware = middlewares[index++]
return middleware(req, executeNext)
}
return executeNext()
}
}
// 使用示例
const combinedMiddleware = combineMiddleware(
logMiddleware,
corsMiddleware,
rateLimitMiddleware
)
const routes = defineRoutes([
{
method: 'GET',
path: '/api/users',
middleware: [combinedMiddleware],
handler: createHandler(() => new Response('Users'))
}
])条件中间件
typescript
const conditionalMiddleware = (condition: (req: Request) => boolean, middleware: any) => {
return async (req: Request, next: () => Promise<Response>) => {
if (condition(req)) {
return middleware(req, next)
}
return next()
}
}
// 使用示例
const adminOnly = conditionalMiddleware(
(req) => req.url.includes('/admin'),
authMiddleware
)
const routes = defineRoutes([
{
method: 'GET',
path: '/admin/users',
middleware: [adminOnly],
handler: createHandler(() => new Response('Admin users'))
}
])全局中间件
您可以为整个应用或特定路径前缀应用中间件:
typescript
const routes = defineRoutes([
{
path: '/api',
middleware: [logMiddleware, corsMiddleware], // 应用到所有 /api 路由
children: [
{
method: 'GET',
path: '/users',
handler: createHandler(() => new Response('Users'))
},
{
method: 'GET',
path: '/posts',
handler: createHandler(() => new Response('Posts'))
}
]
}
])中间件最佳实践
1. 保持中间件简单
typescript
// 好的做法:每个中间件只做一件事
const logRequest = async (req: Request, next: () => Promise<Response>) => {
console.log(`${req.method} ${req.url}`)
return next()
}
const logResponse = async (req: Request, next: () => Promise<Response>) => {
const response = await next()
console.log(`Response: ${response.status}`)
return response
}
// 不好的做法:一个中间件做太多事
const logEverything = async (req: Request, next: () => Promise<Response>) => {
// 记录请求
console.log(`${req.method} ${req.url}`)
// 验证 token
const token = req.headers.get('authorization')
if (!token) return new Response('Unauthorized', { status: 401 })
// 记录响应
const response = await next()
console.log(`Response: ${response.status}`)
return response
}2. 错误处理
typescript
const safeMiddleware = (middleware: any) => {
return async (req: Request, next: () => Promise<Response>) => {
try {
return await middleware(req, next)
} catch (error) {
console.error('Middleware error:', error)
return new Response('Middleware error', { status: 500 })
}
}
}
// 使用安全中间件
const routes = defineRoutes([
{
method: 'GET',
path: '/api/users',
middleware: [safeMiddleware(authMiddleware)],
handler: createHandler(() => new Response('Users'))
}
])3. 中间件顺序
typescript
const routes = defineRoutes([
{
method: 'GET',
path: '/api/users',
middleware: [
logMiddleware, // 1. 日志记录
corsMiddleware, // 2. CORS 处理
rateLimitMiddleware, // 3. 速率限制
authMiddleware, // 4. 身份验证
errorHandler // 5. 错误处理
],
handler: createHandler(() => new Response('Users'))
}
])4. 中间件测试
typescript
// 测试中间件
const testMiddleware = async (middleware: any, req: Request) => {
let executed = false
const next = async () => {
executed = true
return new Response('Test response')
}
const result = await middleware(req, next)
return {
executed,
result,
status: result.status
}
}
// 测试示例
const testReq = new Request('http://localhost:3000/test')
const testResult = await testMiddleware(logMiddleware, testReq)
console.log('Test result:', testResult)总结
Vafast 的中间件系统提供了:
- ✅ 灵活的中间件定义
- ✅ 可预测的执行顺序
- ✅ 强大的错误处理
- ✅ 中间件组合和复用
- ✅ 全局和局部应用
- ✅ 类型安全的实现
