echo中间件本质是接收并返回echo.handlerfunc的函数,必须调用next(c)且通常需return其error;可提前return error终止请求;注册位置决定作用范围;读body后须重置否则后续handler无法读取。

怎么写一个最简自定义中间件
Echo的中间件本质就是一个函数,接收 echo.HandlerFunc,返回新的 echo.HandlerFunc。它必须调用 next(c) 才能让请求继续往下走,否则请求就卡住了。
常见错误是忘记 return next(c),或者在 return 前加了额外逻辑但没处理 error:
- 漏掉
return:导致 handler 不执行,响应空或超时 - 写了
next(c)但没return:后续代码仍会执行,可能重复写响应体,触发http: multiple response.WriteHeader calls - 在
next(c)后还调用了c.JSON()或c.String():同样会 panic
正确写法示例:
func loggingMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
start := time.Now()
err := next(c) // 必须调用且通常要 return
log.Printf("%s %s %v", c.Request().Method, c.Request().URL.Path, time.Since(start))
return err
}
}
如何在中间件里提前终止请求(比如鉴权失败)
中间件里可以直接返回 error,Echo 会立即中断后续 handler,并走错误处理流程(如 HTTPErrorHandler)。不需要手动调用 c.Response().WriteHeader() 或 c.String() —— 那样容易和框架冲突。
典型场景是 token 校验失败:
- 检查
c.Request().Header.Get("Authorization") - 解析 Bearer token,验证有效性
- 校验失败时直接
return c.NoContent(http.StatusUnauthorized) 或 <code>return c.JSON(http.StatusForbidden, ...) - 不要用
http.Error(),它绕过 Echo 的响应生命周期,会丢日志、不触发 recover 中间件
注意:c.JSON() 等方法内部已设置状态码和 header,返回即可,Echo 会接管后续写响应过程。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
中间件注册位置影响作用范围
注册方式决定中间件生效层级,不是所有地方都能用 e.Use():
-
e.Use(mw):全局中间件,对所有路由生效(包括未分组的路由) -
api.Use(mw):只对/api及其子路由(如/api/users)生效 -
e.GET("/health", mw, handler):仅对该路由生效,注意参数顺序:中间件在 handler 前 -
e.Pre(mw):在路由匹配前执行,不能访问c.Param()或c.QueryParam(),适合路径标准化(如补 /)
特别注意:子路由组默认继承父组中间件,但可以调用 group.Reset() 清除继承的中间件,再重新 Use() —— 这个行为容易被忽略,导致预期外的中间件叠加。
中间件里读取/修改请求体的坑
如果中间件需要读 body(比如做签名校验、审计日志),必须小心:HTTP body 是 io.ReadCloser,只能读一次。直接 io.ReadAll(c.Request().Body) 会导致后续 handler 拿不到原始 body。
解决办法只有两个:
- 用
c.Request().Body前先调用c.Request().Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))把内容“还回去”(Go 1.19+ 推荐用bytes.NewReader()) - 更稳妥的做法是使用官方
middleware.BodyDump()或自己封装:读完后重置 Body,同时把原始 bytes 存到c.Set("raw_body", data)供后续 handler 取用
别试图在中间件里反复 ReadAll,也别依赖 c.Request().Body 在多次调用中保持可读性 —— 它不是幂等的。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










