Echo框架中响应头必须手动设置charset=utf-8,因c.JSON()等方法仅设application/json而不含charset,易致老旧客户端误判编码;需显式调用Header().Set()或使用白名单中间件补全。

echo.Response.Header().Set("Content-Type") 必须手动加 charset=utf-8
Echo 默认不自动设置 Content-Type 的字符编码,即使你用 c.String() 或 c.JSON(),响应头也只含 text/plain; charset=utf-8 或 application/json,但后者根本没带 charset —— 而 JSON RFC 明确要求 UTF-8 编码时应显式声明,否则某些老旧客户端(如部分 Java HttpClient、IE11)可能误判为 ISO-8859-1。
正确做法是在写响应前手动补全:
c.Response().Header().Set("Content-Type", "application/json; charset=utf-8")
return c.JSON(200, map[string]string{"msg": "你好"})
- 别依赖
c.JSON()自动加 charset:它只设application/json,不加charset - 对
c.HTML()同理,需手动设text/html; charset=utf-8,否则中文模板变量可能乱码 - 若用
c.String()返回纯文本,也建议显式写text/plain; charset=utf-8,避免终端或 curl -i 解析错位
全局统一设置 Content-Type charset 的中间件写法
重复写 Header().Set() 容易遗漏,适合用中间件兜底。但注意:不能无差别覆盖所有响应,比如文件下载(Content-Type: application/octet-stream)不该加 charset,否则浏览器可能拒绝解析。
推荐按 MIME 类型白名单控制:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
func CharsetMiddleware() echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
if ct := c.Response().Header().Get("Content-Type"); ct != "" {
switch {
case strings.HasPrefix(ct, "text/"),
strings.HasPrefix(ct, "application/json"),
ct == "application/javascript",
ct == "application/xml":
c.Response().Header().Set("Content-Type", ct+"; charset=utf-8")
}
}
return next(c)
})
}
}
- 注册时放在
e.Use()链靠后位置(比如 logger 之后、recover 之前),确保 header 尚未写出 - 不要在中间件里调用
c.Set("Content-Type", ...):那是无效的,必须操作c.Response().Header() - 若上游 handler 已手动设了完整
Content-Type(含 charset),此中间件会二次拼接出错,所以开头先Get()判断是否已存在
echo.Renderer 渲染 HTML 模板时 charset 容易被忽略
用 e.Renderer = &CustomRenderer{} 自定义模板引擎时,Render() 方法里若只写 c.Response().WriteHeader(200) 和 t.Execute(...),响应头完全空白,浏览器默认按系统 locale 解码,中文必乱。
必须在 Render() 中主动写头:
func (r *CustomRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
c.Response().Header().Set("Content-Type", "text/html; charset=utf-8")
return r.template.ExecuteTemplate(w, name, data)
}
- 别指望
html/template自己输出 meta 标签就能解决:HTTP header 优先级永远高于<meta charset> - 如果模板里用了
{{.Title}}这类动态内容,且数据本身是 GBK 编码(极少见但存在),需先转 UTF-8 再传入,否则 header 设对也没用 - 使用
gin-contrib/render等第三方 renderer 时,确认其源码是否已处理 charset;很多只是简单包装,没补 header
curl 或 Postman 测试时看到乱码,不一定是服务端问题
现象:服务端明明写了 charset=utf-8,但 curl -v 看到响应体仍是乱码。大概率是终端编码不匹配,而非 Echo 配置错误。
- Linux/macOS 终端检查:
locale | grep UTF,若输出不含UTF-8,运行export LANG=en_US.UTF-8 - Windows CMD 默认是 GBK,
chcp 65001切到 UTF-8 后再测 - Postman 默认按响应头解析,但若手动点开 “Preview” 标签页,它有时会缓存旧响应,强制点 “Send and Download” 另存为文件再用编辑器打开验证
- 真正可靠的验证方式:用浏览器开发者工具看 Network → Response Headers → Content-Type 是否含
charset=utf-8,再看 Preview 是否正常显示中文
c.HTML() 调用,对应页面就可能在某款浏览器里崩掉。


















