HTTP 中间件总览
把日志、恢复、限流、认证、安全 Header 等横切能力接入路由
中间件适合处理所有 HTTP 请求都可能用到的横切逻辑,比如 panic 恢复、请求 ID、真实 IP、访问日志、CORS、CSRF、请求体大小限制、超时、静态文件、登录态、权限、限流和审计。
Runa 的中间件类型是 route.Middleware,本质是 func(route.Handler) route.Handler。它只属于 HTTP route 传输块,不进入微内核,也不是 Provider。普通应用开发者只需要理解三件事:安装需要的包、把中间件挂到合适位置、把依赖能力先通过 runa.Install 装好。
安装
只使用路由机制时安装 route:
go get github.com/duxweb/runa/route
使用官方内置 HTTP 中间件时安装 middleware 模块:
go get github.com/duxweb/runa/middleware
语言协商中间件是独立模块:
go get github.com/duxweb/runa/middleware/lang
使用组合安全预设时安装 security 模块:
go get github.com/duxweb/runa/security
业务中间件按能力单独安装,比如 session、auth、rate、audit:
go get github.com/duxweb/runa/session github.com/duxweb/runa/auth github.com/duxweb/runa/rate github.com/duxweb/runa/audit
最小示例
package main
import (
"context"
"github.com/duxweb/runa"
"github.com/duxweb/runa/route"
"github.com/duxweb/runa/security"
)
func main() {
app := runa.New()
app.Install(route.Provider(route.Addr(":8080")))
route.Default().Use(security.New(security.Production()))
route.Default().Get("/", func(ctx *route.Context) error {
return ctx.Text("ok")
})
if err := app.Run(context.Background()); err != nil {
panic(err)
}
}
挂载位置
全局挂载,适合 recover、request id、real ip、logger、security 这类全站逻辑:
route.Default().Use(mw)
分组挂载,适合只保护某一组接口:
api := route.Default().Group("/api")
api.Use(mw)
单路由挂载,适合只给少数接口加权限或限流:
route.Default().Get("/profile", profile).Use(mw)
执行顺序
中间件按注册顺序进入,按相反顺序退出:
route.Default().Use(A(), B(), C())
A before -> B before -> C before -> handler -> C after -> B after -> A after
通常推荐顺序:
recover最外层,兜住后续中间件和 handler 的 panicrequestid早注册,让日志、审计、错误响应都能拿到请求 IDrealip早注册,让日志、限流、审计拿到真实 IPlogger记录最终状态码和耗时bodylimit、timeout保护资源helmet、cors设置响应 Headersession、auth、rate、audit按业务需要挂到分组或路由
如果不想自己组合基础链路,可以直接用 Security 生产预设
跳过请求
大多数官方中间件都有 Next func(*route.Context) bool 配置。返回 true 表示跳过当前中间件。
route.Default().Use(logger.New(logger.Config{
Next: func(ctx *route.Context) bool {
return ctx.Request().URL.Path == "/health"
},
}))
适合跳过 /health、/metrics、静态文件、内部回调等请求。
页面索引
| 页面 | 适合解决的问题 |
|---|---|
| Recover | 捕获 panic,避免进程因为单个请求崩溃 |
| Request ID | 给每个请求生成追踪 ID |
| Real IP | 从可信代理读取真实客户端 IP |
| Logger | 记录 HTTP 访问日志、慢请求和错误请求 |
| CORS | 允许浏览器跨域访问 API |
| CSRF | 保护浏览器表单和 Cookie 登录态接口 |
| Body Limit | 限制请求体大小,避免大包拖垮服务 |
| Timeout | 给普通 HTTP 请求设置最大执行时间 |
| Helmet | 写入常见安全 Header |
| Healthcheck | 快速提供 /health 健康检查 |
| Static | 挂载本地静态文件目录 |
| Security | 一次接入生产常用安全链路 |
| Session | 在请求中加载和保存会话 |
| Auth | 登录态、可选登录和权限检查 |
| Rate Limit | 按 IP、用户或自定义键限流 |
| Audit | 记录业务操作审计日志 |
新手怎么选择中间件
可以按这个顺序理解:
- 先加基础保护:recover、requestid、realip、logger、bodylimit、timeout、helmet
- 如果有浏览器跨域,再加 CORS
- 如果有浏览器表单或 Cookie 登录态,再加 CSRF
- 如果有登录态,再加 session 和 auth
- 如果接口容易被刷,再加 rate
- 如果后台操作需要追踪,再加 audit
如果不想逐个配置,先用 安全预设 起步,再按项目需要微调。
如果你只做一个内部极简 HTTP 服务,也可以只挂 recover.New() 和 requestid.New()。Runa 不强制安装任何中间件,所有中间件都按需 import、按需挂载。