在echo中,中间件应通过c.request().url.path获取已解码的请求路径,并将日志中间件注册在e.use()最前以覆盖所有请求;需避免使用c.path()或rawpath,建议结合耗时统计与状态码记录,并确保覆盖健康检查等所有入口。

中间件里怎么拿到请求路径
在 Echo 中,echo.Context 提供了 c.Request().URL.Path 和 c.Request().URL.RawPath 两种方式获取路径。推荐用 c.Request().URL.Path,它已做 URL 解码,不会因路径含中文或特殊字符而出错;而 RawPath 是原始未解码字符串,容易在日志中显示为 %E4%BD%A0%E5%A5%BD 这类编码,不利于排查。
记录路径的中间件怎么写才不漏请求
必须在路由匹配前执行日志逻辑,否则某些 404 或预处理失败的请求可能绕过中间件。正确写法是把日志中间件注册在 e.Use() 队列最前面:
e := echo.New()
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
path := c.Request().URL.Path
log.Printf("REQ: %s %s", c.Request().Method, path)
return next(c)
}
})
// 后续再注册路由和其它中间件
- 别放在
e.GET()等路由方法内部,那只是 handler 层级,不是中间件 - 别用
c.Path()—— 它返回的是路由定义模板(如/users/:id),不是真实请求路径 - 如果用了
e.Pre(),它只对静态文件生效,不适用于普通 API 请求
为什么日志里有时看到重复路径或空路径
常见于以下几种情况:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 客户端发起 OPTIONS 预检请求,但没配置
CORS中间件,导致请求被拦截前就进日志中间件,此时path可能为空或为/ - 使用了
e.Static(),静态文件中间件会提前响应,但日志中间件仍会执行一次 —— 建议加判断:if !strings.HasPrefix(path, "/static/") { ... } - 反向代理(如 Nginx)没透传
X-Forwarded-Proto或X-Real-IP,但路径本身不受影响;真正影响路径的是ProxyURI设置错误,导致Request.URL被重写
要不要加耗时统计和状态码
单纯记录路径意义有限,建议顺手补上基础指标。Echo 的中间件天然支持 defer 执行,适合统计耗时:
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
start := time.Now()
path := c.Request().URL.Path
err := next(c)
status := c.Response().Status
dur := time.Since(start).Milliseconds()
log.Printf("REQ: %s %s %d %dms", c.Request().Method, path, status, int64(dur))
return err
}
})
注意 c.Response().Status 在 next(c) 返回后才可读取,不能在调用前读 —— 否则永远是 0 或默认 200。
路径记录本身很简单,但实际部署时最容易被忽略的是:日志中间件是否覆盖了所有入口(比如健康检查 /health、Prometheus /metrics、pprof 调试端点),以及是否和链路追踪 ID(如 X-Request-ID)做了关联。这些不补全,单看路径很难定位真实问题。










