1. 中间件分类
gozero默认中间件
通过在api文件中创建的中间件
通过server.Use(middleware Middleware)创建的中间件
2. 中间件介绍
2.1 gozero默认中间件
默认中间件包括如下:

在gozero中对应的代码为:
go
// 文件位置:github.com\zeromicro\[email protected]\rest\engine.go
func (ng *engine) buildChainWithNativeMiddlewares(fr featuredRoutes, route Route,
metrics *stat.Metrics) chain.Chain {
chn := chain.New()
if ng.conf.Middlewares.Trace {
chn = chn.Append(handler.TraceHandler(ng.conf.Name,
route.Path,
handler.WithTraceIgnorePaths(ng.conf.TraceIgnorePaths)))
}
if ng.conf.Middlewares.Log {
chn = chn.Append(ng.getLogHandler())
}
if ng.conf.Middlewares.Prometheus {
chn = chn.Append(handler.PrometheusHandler(route.Path, route.Method))
}
if ng.conf.Middlewares.MaxConns {
chn = chn.Append(handler.MaxConnsHandler(ng.conf.MaxConns))
}
if ng.conf.Middlewares.Breaker {
chn = chn.Append(handler.BreakerHandler(route.Method, route.Path, metrics))
}
if ng.conf.Middlewares.Shedding {
chn = chn.Append(handler.SheddingHandler(ng.getShedder(fr.priority), metrics))
}
if ng.conf.Middlewares.Timeout {
chn = chn.Append(handler.TimeoutHandler(ng.checkedTimeout(fr.timeout)))
}
if ng.conf.Middlewares.Recover {
chn = chn.Append(handler.RecoverHandler)
}
if ng.conf.Middlewares.Metrics {
chn = chn.Append(handler.MetricHandler(metrics))
}
if ng.conf.Middlewares.MaxBytes {
chn = chn.Append(handler.MaxBytesHandler(ng.checkedMaxBytes(fr.maxBytes)))
}
if ng.conf.Middlewares.Gunzip {
chn = chn.Append(handler.GunzipHandler)
}
return chn
}
没有jwt.auth的?
搁着了,哈哈
go
// github.com\zeromicro\[email protected]\rest\engine.go
// 注意这段代码,一会还要用!!!
func (ng *engine) bindRoute(fr featuredRoutes, router httpx.Router, metrics *stat.Metrics,
route Route, verifier func(chain.Chain) chain.Chain) error {
chn := ng.chain
if chn == nil {
chn = ng.buildChainWithNativeMiddlewares(fr, route, metrics)
}
chn = ng.appendAuthHandler(fr, chn, verifier) //搁着了,哈哈
for _, middleware := range ng.middlewares {
chn = chn.Append(convertMiddleware(middleware))
}
handle := chn.ThenFunc(route.Handler)
return router.Handle(route.Method, route.Path, handle)
}
2.2 通过在api文件中创建的中间件
在制作api文件时,可以通过如下代码生成中间件
go
@server(
middleware: checkMiddleware, testMiddleware // 中间件, 多个中间件用逗号分割
)
最终生成的中间件位于
go
// api/internal/handler/routes.go
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.CheckMiddleware, serverCtx.TestMiddleware},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/Info/get",
Handler: demo.GetInfoHandler(serverCtx),
},
}...,
),
rest.WithPrefix("/api/demo/v1"),
)
}
根据代码可以判断出,该方式生成的中间件与路径绑定,并一起注册到server中。
2.3 通过server.Use(middleware Middleware)创建的中间件
我们还可以通过调用server.Use(middleware Middleware)函数创建中间件:
go
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
server.Use(ctx.CheckMiddleware)
// 多个可多次调用,最终是append到list的
具体函数信息:
go
// github.com\zeromicro\[email protected]\rest\server.go
// Use adds the given middleware in the Server.
func (s *Server) Use(middleware Middleware) {
s.ngin.use(middleware)
}
func (ng *engine) use(middleware Middleware) {
ng.middlewares = append(ng.middlewares, middleware)
}
3. 中间件的执行顺序
通过上述介绍,我们可以发现,gozero存在三种中间件(个人理解),那么这三种中间件的执行顺序是咋样的呢,哪个先执行,哪个后执行?
**答案:**先是默认中间件,再是use的中间件,最后是api生成的中间件。当然,各部分内部执行顺序遵循中间件执行顺序。
原理:
go
// github.com\zeromicro\[email protected]\rest\engine.go
func (ng *engine) bindRoute(fr featuredRoutes, router httpx.Router, metrics *stat.Metrics,
route Route, verifier func(chain.Chain) chain.Chain) error {
chn := ng.chain
if chn == nil {
chn = ng.buildChainWithNativeMiddlewares(fr, route, metrics) // 默认中间件加载
}
chn = ng.appendAuthHandler(fr, chn, verifier) // 认证中间件
for _, middleware := range ng.middlewares {
chn = chn.Append(convertMiddleware(middleware)) // use中间件加载
}
handle := chn.ThenFunc(route.Handler) // route中间件加载
return router.Handle(route.Method, route.Path, handle)
}
总体流程:
go
server.Start()--->
start() --->
bindRoutes() --->
bindFeaturedRoutes() --->
bindRoute()
4. 默认中间件关闭
查看gozero默认配置项,如下:
go
MiddlewaresConf struct {
Trace bool `json:",default=true"`
Log bool `json:",default=true"`
Prometheus bool `json:",default=true"`
MaxConns bool `json:",default=true"`
Breaker bool `json:",default=true"`
Shedding bool `json:",default=true"`
Timeout bool `json:",default=true"`
Recover bool `json:",default=true"`
Metrics bool `json:",default=true"`
MaxBytes bool `json:",default=true"`
Gunzip bool `json:",default=true"`
}
RestConf struct {
service.ServiceConf
Host string `json:",default=0.0.0.0"`
Port int
CertFile string `json:",optional"`
KeyFile string `json:",optional"`
Verbose bool `json:",optional"`
MaxConns int `json:",default=10000"`
MaxBytes int64 `json:",default=1048576"`
// milliseconds
Timeout int64 `json:",default=3000"`
CpuThreshold int64 `json:",default=900,range=[0:1000)"`
Signature SignatureConf `json:",optional"`
// There are default values for all the items in Middlewares.
Middlewares MiddlewaresConf
// TraceIgnorePaths is paths blacklist for trace middleware.
TraceIgnorePaths []string `json:",optional"`
}
因此,要关闭某一默认中间件,直接在配置文件中设置false就可以了。
yaml
# 例如:
Name: demo-api
Host: 0.0.0.0
Port: 8888
Middlewares:
Prometheus: false