hono-middleware by bobmatnyc/claude-mpm-skills
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill hono-middlewareHono 提供了一个强大的中间件系统,采用“洋葱”执行模型。中间件在处理器之前处理请求,在处理器之后处理响应,从而实现诸如身份验证、日志记录和 CORS 等横切关注点。
主要特性:
createMiddleware 创建类型安全的中间件在以下场景中使用 Hono 中间件:
import { Hono } from 'hono'
const app = new Hono()
// 简单的日志记录中间件
app.use('*', async (c, next) => {
console.log(`[${c.req.method}] ${c.req.url}`)
await next()
})
// 路径特定的中间件
app.use('/api/*', async (c, next) => {
const start = Date.now()
await next()
const ms = Date.now() - start
c.header('X-Response-Time', `${ms}ms`)
})
app.use(async (c, next) => {
console.log('1. 之前(最先进入)')
await next()
console.log('6. 之后(最后退出)')
})
app.use(async (c, next) => {
console.log('2. 之前(第二进入)')
await next()
console.log('5. 之后(第二退出)')
})
app.use(async (c, next) => {
console.log('3. 之前(第三进入)')
await next()
console.log('4. 之后(第三退出)')
})
app.get('/', (c) => {
console.log('处理器')
return c.text('Hello!')
})
// 输出:
// 1. 之前(最先进入)
// 2. 之前(第二进入)
// 3. 之前(第三进入)
// 处理器
// 4. 之后(第三退出)
// 5. 之后(第二退出)
// 6. 之后(最后退出)
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
import { createMiddleware } from 'hono/factory'
// 类型安全的可重用中间件
const logger = createMiddleware(async (c, next) => {
console.log(`[${new Date().toISOString()}] ${c.req.method} ${c.req.path}`)
await next()
})
// 带选项的中间件
const timing = (headerName = 'X-Response-Time') => {
return createMiddleware(async (c, next) => {
const start = Date.now()
await next()
c.header(headerName, `${Date.now() - start}ms`)
})
}
app.use(logger)
app.use(timing('X-Duration'))
import { createMiddleware } from 'hono/factory'
// 定义变量类型
type Variables = {
user: { id: string; email: string; role: string }
requestId: string
}
const app = new Hono<{ Variables: Variables }>()
// 身份验证中间件设置用户
const auth = createMiddleware<{ Variables: Variables }>(async (c, next) => {
const token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) {
return c.json({ error: 'Unauthorized' }, 401)
}
const user = await verifyToken(token)
c.set('user', user) // 类型安全!
await next()
})
// 请求 ID 中间件
const requestId = createMiddleware<{ Variables: Variables }>(async (c, next) => {
c.set('requestId', crypto.randomUUID())
await next()
})
app.use(requestId)
app.use('/api/*', auth)
app.get('/api/profile', (c) => {
const user = c.get('user') // 类型:{ id, email, role }
const reqId = c.get('requestId') // 类型:string
return c.json({ user, requestId: reqId })
})
import { cors } from 'hono/cors'
// 简单 - 允许所有来源
app.use('/api/*', cors())
// 已配置
app.use('/api/*', cors({
origin: ['https://example.com', 'https://app.example.com'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization'],
exposeHeaders: ['X-Total-Count'],
credentials: true,
maxAge: 86400
}))
// 动态来源
app.use('/api/*', cors({
origin: (origin) => {
return origin.endsWith('.example.com')
? origin
: 'https://example.com'
}
}))
import { bearerAuth } from 'hono/bearer-auth'
// 简单的令牌验证
app.use('/api/*', bearerAuth({ token: 'my-secret-token' }))
// 多个令牌
app.use('/api/*', bearerAuth({
token: ['token1', 'token2', 'token3']
}))
// 自定义验证
app.use('/api/*', bearerAuth({
verifyToken: async (token, c) => {
const user = await validateJWT(token)
if (user) {
c.set('user', user)
return true
}
return false
}
}))
import { basicAuth } from 'hono/basic-auth'
app.use('/admin/*', basicAuth({
username: 'admin',
password: 'secret' // pragma: allowlist secret
}))
// 多个用户
app.use('/admin/*', basicAuth({
verifyUser: (username, password, c) => {
return username === 'admin' && password === process.env.ADMIN_PASSWORD
}
}))
import { jwt } from 'hono/jwt'
app.use('/api/*', jwt({
secret: 'my-jwt-secret' // pragma: allowlist secret
}))
// 在处理器中访问有效负载
app.get('/api/profile', (c) => {
const payload = c.get('jwtPayload')
return c.json({ userId: payload.sub })
})
// 带算法
app.use('/api/*', jwt({
secret: 'secret', // pragma: allowlist secret
alg: 'HS256'
}))
import { logger } from 'hono/logger'
// 默认格式
app.use(logger())
// 自定义格式
app.use(logger((str, ...rest) => {
console.log(`[API] ${str}`, ...rest)
}))
// 输出:<-- GET /api/users
// --> GET /api/users 200 12ms
import { prettyJSON } from 'hono/pretty-json'
// 添加 ?pretty 以格式化 JSON 响应
app.use(prettyJSON())
// GET /api/users → {"users":[...]}
// GET /api/users?pretty → 格式化的 JSON
import { compress } from 'hono/compress'
app.use(compress())
// 带选项
app.use(compress({
encoding: 'gzip' // 'gzip' | 'deflate'
}))
import { etag } from 'hono/etag'
app.use(etag())
// 弱 ETag
app.use(etag({ weak: true }))
import { cache } from 'hono/cache'
// Cloudflare Workers 缓存
app.use('/static/*', cache({
cacheName: 'my-app',
cacheControl: 'max-age=3600'
}))
import { secureHeaders } from 'hono/secure-headers'
app.use(secureHeaders())
// 已配置
app.use(secureHeaders({
contentSecurityPolicy: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"]
},
xFrameOptions: 'DENY',
xXssProtection: '1; mode=block'
}))
import { csrf } from 'hono/csrf'
app.use(csrf())
// 带选项
app.use(csrf({
origin: ['https://example.com']
}))
import { timeout } from 'hono/timeout'
// 5 秒超时
app.use('/api/*', timeout(5000))
// 自定义错误
app.use('/api/*', timeout(5000, () => {
return new Response('请求超时', { status: 408 })
}))
import { requestId } from 'hono/request-id'
app.use(requestId())
app.get('/', (c) => {
const id = c.get('requestId')
return c.json({ requestId: id })
})
// 根据条件应用中间件
const conditionalAuth = createMiddleware(async (c, next) => {
// 对健康检查跳过身份验证
if (c.req.path === '/health') {
return next()
}
// 对其他所有内容应用身份验证
const token = c.req.header('Authorization')
if (!token) {
return c.json({ error: 'Unauthorized' }, 401)
}
await next()
})
import { every, some } from 'hono/combine'
// 所有中间件必须通过
const strictAuth = every(
bearerAuth({ token: 'secret' }),
ipRestriction(['192.168.1.0/24']),
rateLimiter({ max: 100 })
)
// 任何中间件可以通过
const flexibleAuth = some(
bearerAuth({ token: 'api-key' }),
basicAuth({ username: 'user', password: 'pass' }) // pragma: allowlist secret
)
app.use('/api/*', strictAuth)
app.use('/public/*', flexibleAuth)
const addHeaders = createMiddleware(async (c, next) => {
await next()
// 在处理器之后修改响应
c.res.headers.set('X-Powered-By', 'Hono')
c.res.headers.set('X-Request-Id', c.get('requestId'))
})
const transformResponse = createMiddleware(async (c, next) => {
await next()
// 完全替换响应
const originalBody = await c.res.json()
c.res = new Response(
JSON.stringify({ data: originalBody, timestamp: Date.now() }),
c.res
)
})
import { HTTPException } from 'hono/http-exception'
const safeMiddleware = createMiddleware(async (c, next) => {
try {
await next()
} catch (error) {
if (error instanceof HTTPException) {
throw error // 重新抛出 HTTP 异常
}
// 记录并转换其他错误
console.error('中间件错误:', error)
throw new HTTPException(500, { message: '内部错误' })
}
})
// 简单的内存速率限制器
const rateLimiter = (options: { max: number; window: number }) => {
const requests = new Map<string, { count: number; reset: number }>()
return createMiddleware(async (c, next) => {
const ip = c.req.header('CF-Connecting-IP') || 'unknown'
const now = Date.now()
let record = requests.get(ip)
if (!record || now > record.reset) {
record = { count: 0, reset: now + options.window }
requests.set(ip, record)
}
record.count++
if (record.count > options.max) {
c.header('Retry-After', String(Math.ceil((record.reset - now) / 1000)))
return c.json({ error: '超出速率限制' }, 429)
}
c.header('X-RateLimit-Limit', String(options.max))
c.header('X-RateLimit-Remaining', String(options.max - record.count))
await next()
})
}
app.use('/api/*', rateLimiter({ max: 100, window: 60000 }))
const app = new Hono()
// 1. 请求 ID(最先 - 用于跟踪)
app.use(requestId())
// 2. 日志记录器(尽早 - 记录所有请求)
app.use(logger())
// 3. 安全头部
app.use(secureHeaders())
// 4. CORS(在身份验证之前 - 用于预检)
app.use('/api/*', cors())
// 5. 压缩
app.use(compress())
// 6. 速率限制
app.use('/api/*', rateLimiter({ max: 100, window: 60000 }))
// 7. 身份验证
app.use('/api/*', bearerAuth({ verifyToken }))
// 8. 请求验证(在身份验证之后)
app.use('/api/*', validator)
// 9. 路由
app.route('/api', apiRoutes)
// 10. 未找到处理器(最后)
app.notFound((c) => c.json({ error: '未找到' }, 404))
| 中间件 | 导入 | 用途 |
|---|---|---|
cors | hono/cors | 跨域请求 |
bearerAuth | hono/bearer-auth | Bearer 令牌身份验证 |
basicAuth | hono/basic-auth | HTTP 基本身份验证 |
jwt | hono/jwt | JWT 验证 |
logger | hono/logger | 请求日志记录 |
prettyJSON | hono/pretty-json | JSON 格式化 |
compress | hono/compress | 响应压缩 |
etag | hono/etag | ETag 头部 |
cache | hono/cache | 响应缓存 |
secureHeaders | hono/secure-headers | 安全头部 |
csrf | hono/csrf | CSRF 保护 |
timeout | hono/timeout | 请求超时 |
requestId | hono/request-id | 请求 ID 头部 |
npm install @hono/zod-validator # Zod 验证
npm install @hono/graphql-server # GraphQL
npm install @hono/swagger-ui # Swagger UI
npm install @hono/prometheus # Prometheus 指标
npm install @hono/sentry # Sentry 错误跟踪
版本 : Hono 4.x 最后更新 : 2025 年 1 月 许可证 : MIT
每周安装数
128
代码仓库
GitHub 星标数
18
首次出现
2026 年 1 月 23 日
安全审计
已安装于
opencode104
gemini-cli100
codex98
github-copilot96
claude-code89
kimi-cli77
Hono provides a powerful middleware system with an "onion" execution model. Middleware processes requests before handlers and responses after handlers, enabling cross-cutting concerns like authentication, logging, and CORS.
Key Features :
createMiddlewareUse Hono middleware when:
import { Hono } from 'hono'
const app = new Hono()
// Simple logging middleware
app.use('*', async (c, next) => {
console.log(`[${c.req.method}] ${c.req.url}`)
await next()
})
// Path-specific middleware
app.use('/api/*', async (c, next) => {
const start = Date.now()
await next()
const ms = Date.now() - start
c.header('X-Response-Time', `${ms}ms`)
})
app.use(async (c, next) => {
console.log('1. Before (first in)')
await next()
console.log('6. After (first out)')
})
app.use(async (c, next) => {
console.log('2. Before (second in)')
await next()
console.log('5. After (second out)')
})
app.use(async (c, next) => {
console.log('3. Before (third in)')
await next()
console.log('4. After (third out)')
})
app.get('/', (c) => {
console.log('Handler')
return c.text('Hello!')
})
// Output:
// 1. Before (first in)
// 2. Before (second in)
// 3. Before (third in)
// Handler
// 4. After (third out)
// 5. After (second out)
// 6. After (first out)
import { createMiddleware } from 'hono/factory'
// Type-safe reusable middleware
const logger = createMiddleware(async (c, next) => {
console.log(`[${new Date().toISOString()}] ${c.req.method} ${c.req.path}`)
await next()
})
// Middleware with options
const timing = (headerName = 'X-Response-Time') => {
return createMiddleware(async (c, next) => {
const start = Date.now()
await next()
c.header(headerName, `${Date.now() - start}ms`)
})
}
app.use(logger)
app.use(timing('X-Duration'))
import { createMiddleware } from 'hono/factory'
// Define variable types
type Variables = {
user: { id: string; email: string; role: string }
requestId: string
}
const app = new Hono<{ Variables: Variables }>()
// Auth middleware sets user
const auth = createMiddleware<{ Variables: Variables }>(async (c, next) => {
const token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) {
return c.json({ error: 'Unauthorized' }, 401)
}
const user = await verifyToken(token)
c.set('user', user) // Type-safe!
await next()
})
// Request ID middleware
const requestId = createMiddleware<{ Variables: Variables }>(async (c, next) => {
c.set('requestId', crypto.randomUUID())
await next()
})
app.use(requestId)
app.use('/api/*', auth)
app.get('/api/profile', (c) => {
const user = c.get('user') // Type: { id, email, role }
const reqId = c.get('requestId') // Type: string
return c.json({ user, requestId: reqId })
})
import { cors } from 'hono/cors'
// Simple - allow all origins
app.use('/api/*', cors())
// Configured
app.use('/api/*', cors({
origin: ['https://example.com', 'https://app.example.com'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization'],
exposeHeaders: ['X-Total-Count'],
credentials: true,
maxAge: 86400
}))
// Dynamic origin
app.use('/api/*', cors({
origin: (origin) => {
return origin.endsWith('.example.com')
? origin
: 'https://example.com'
}
}))
import { bearerAuth } from 'hono/bearer-auth'
// Simple token validation
app.use('/api/*', bearerAuth({ token: 'my-secret-token' }))
// Multiple tokens
app.use('/api/*', bearerAuth({
token: ['token1', 'token2', 'token3']
}))
// Custom verification
app.use('/api/*', bearerAuth({
verifyToken: async (token, c) => {
const user = await validateJWT(token)
if (user) {
c.set('user', user)
return true
}
return false
}
}))
import { basicAuth } from 'hono/basic-auth'
app.use('/admin/*', basicAuth({
username: 'admin',
password: 'secret' // pragma: allowlist secret
}))
// Multiple users
app.use('/admin/*', basicAuth({
verifyUser: (username, password, c) => {
return username === 'admin' && password === process.env.ADMIN_PASSWORD
}
}))
import { jwt } from 'hono/jwt'
app.use('/api/*', jwt({
secret: 'my-jwt-secret' // pragma: allowlist secret
}))
// Access payload in handler
app.get('/api/profile', (c) => {
const payload = c.get('jwtPayload')
return c.json({ userId: payload.sub })
})
// With algorithm
app.use('/api/*', jwt({
secret: 'secret', // pragma: allowlist secret
alg: 'HS256'
}))
import { logger } from 'hono/logger'
// Default format
app.use(logger())
// Custom format
app.use(logger((str, ...rest) => {
console.log(`[API] ${str}`, ...rest)
}))
// Output: <-- GET /api/users
// --> GET /api/users 200 12ms
import { prettyJSON } from 'hono/pretty-json'
// Add ?pretty to format JSON responses
app.use(prettyJSON())
// GET /api/users → {"users":[...]}
// GET /api/users?pretty → formatted JSON
import { compress } from 'hono/compress'
app.use(compress())
// With options
app.use(compress({
encoding: 'gzip' // 'gzip' | 'deflate'
}))
import { etag } from 'hono/etag'
app.use(etag())
// Weak ETags
app.use(etag({ weak: true }))
import { cache } from 'hono/cache'
// Cloudflare Workers cache
app.use('/static/*', cache({
cacheName: 'my-app',
cacheControl: 'max-age=3600'
}))
import { secureHeaders } from 'hono/secure-headers'
app.use(secureHeaders())
// Configured
app.use(secureHeaders({
contentSecurityPolicy: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"]
},
xFrameOptions: 'DENY',
xXssProtection: '1; mode=block'
}))
import { csrf } from 'hono/csrf'
app.use(csrf())
// With options
app.use(csrf({
origin: ['https://example.com']
}))
import { timeout } from 'hono/timeout'
// 5 second timeout
app.use('/api/*', timeout(5000))
// Custom error
app.use('/api/*', timeout(5000, () => {
return new Response('Request timeout', { status: 408 })
}))
import { requestId } from 'hono/request-id'
app.use(requestId())
app.get('/', (c) => {
const id = c.get('requestId')
return c.json({ requestId: id })
})
// Apply middleware based on condition
const conditionalAuth = createMiddleware(async (c, next) => {
// Skip auth for health checks
if (c.req.path === '/health') {
return next()
}
// Apply auth for everything else
const token = c.req.header('Authorization')
if (!token) {
return c.json({ error: 'Unauthorized' }, 401)
}
await next()
})
import { every, some } from 'hono/combine'
// All middleware must pass
const strictAuth = every(
bearerAuth({ token: 'secret' }),
ipRestriction(['192.168.1.0/24']),
rateLimiter({ max: 100 })
)
// Any middleware can pass
const flexibleAuth = some(
bearerAuth({ token: 'api-key' }),
basicAuth({ username: 'user', password: 'pass' }) // pragma: allowlist secret
)
app.use('/api/*', strictAuth)
app.use('/public/*', flexibleAuth)
const addHeaders = createMiddleware(async (c, next) => {
await next()
// Modify response after handler
c.res.headers.set('X-Powered-By', 'Hono')
c.res.headers.set('X-Request-Id', c.get('requestId'))
})
const transformResponse = createMiddleware(async (c, next) => {
await next()
// Replace response entirely
const originalBody = await c.res.json()
c.res = new Response(
JSON.stringify({ data: originalBody, timestamp: Date.now() }),
c.res
)
})
import { HTTPException } from 'hono/http-exception'
const safeMiddleware = createMiddleware(async (c, next) => {
try {
await next()
} catch (error) {
if (error instanceof HTTPException) {
throw error // Re-throw HTTP exceptions
}
// Log and convert other errors
console.error('Middleware error:', error)
throw new HTTPException(500, { message: 'Internal error' })
}
})
// Simple in-memory rate limiter
const rateLimiter = (options: { max: number; window: number }) => {
const requests = new Map<string, { count: number; reset: number }>()
return createMiddleware(async (c, next) => {
const ip = c.req.header('CF-Connecting-IP') || 'unknown'
const now = Date.now()
let record = requests.get(ip)
if (!record || now > record.reset) {
record = { count: 0, reset: now + options.window }
requests.set(ip, record)
}
record.count++
if (record.count > options.max) {
c.header('Retry-After', String(Math.ceil((record.reset - now) / 1000)))
return c.json({ error: 'Rate limit exceeded' }, 429)
}
c.header('X-RateLimit-Limit', String(options.max))
c.header('X-RateLimit-Remaining', String(options.max - record.count))
await next()
})
}
app.use('/api/*', rateLimiter({ max: 100, window: 60000 }))
const app = new Hono()
// 1. Request ID (first - for tracking)
app.use(requestId())
// 2. Logger (early - to log all requests)
app.use(logger())
// 3. Security headers
app.use(secureHeaders())
// 4. CORS (before auth - for preflight)
app.use('/api/*', cors())
// 5. Compression
app.use(compress())
// 6. Rate limiting
app.use('/api/*', rateLimiter({ max: 100, window: 60000 }))
// 7. Authentication
app.use('/api/*', bearerAuth({ verifyToken }))
// 8. Request validation (after auth)
app.use('/api/*', validator)
// 9. Routes
app.route('/api', apiRoutes)
// 10. Not found handler (last)
app.notFound((c) => c.json({ error: 'Not found' }, 404))
| Middleware | Import | Purpose |
|---|---|---|
cors | hono/cors | Cross-origin requests |
bearerAuth | hono/bearer-auth | Bearer token auth |
basicAuth | hono/basic-auth | HTTP Basic auth |
jwt |
npm install @hono/zod-validator # Zod validation
npm install @hono/graphql-server # GraphQL
npm install @hono/swagger-ui # Swagger UI
npm install @hono/prometheus # Prometheus metrics
npm install @hono/sentry # Sentry error tracking
Version : Hono 4.x Last Updated : January 2025 License : MIT
Weekly Installs
128
Repository
GitHub Stars
18
First Seen
Jan 23, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode104
gemini-cli100
codex98
github-copilot96
claude-code89
kimi-cli77
lark-cli 共享规则:飞书资源操作指南与权限配置详解
39,000 周安装
hono/jwt |
| JWT verification |
logger | hono/logger | Request logging |
prettyJSON | hono/pretty-json | JSON formatting |
compress | hono/compress | Response compression |
etag | hono/etag | ETag headers |
cache | hono/cache | Response caching |
secureHeaders | hono/secure-headers | Security headers |
csrf | hono/csrf | CSRF protection |
timeout | hono/timeout | Request timeout |
requestId | hono/request-id | Request ID header |