Iris中ctx.JSON()等方法只设置Content-Type和响应体,不修改状态码,故默认始终为200;必须显式调用ctx.StatusCode()提前设定,且需在JSON等写入前执行,否则无效或冲突。

必须显式调用 ctx.StatusCode(),否则默认始终是 200
为什么 ctx.JSON() 或 ctx.Text() 不会自动改状态码
Iris 的 ctx.JSON()、ctx.Text()、ctx.HTML() 等方法只负责序列化内容并设置 Content-Type,它们完全不碰状态码。状态码独立于内容写入逻辑,由 ctx.StatusCode() 单独控制。
- 常见错误:调用
ctx.JSON(iris.Map{"error": "not found"})后前端收到 200 + 错误内容,无法用 HTTP 状态做条件判断 - 正确顺序:先
ctx.StatusCode(iris.StatusNotFound),再ctx.JSON(...);顺序不可颠倒(后设状态码无效) - 如果只写
ctx.StatusCode(404)但没写响应体,浏览器会看到空响应(HTTP 404 但无 body),多数前端库会报错或静默失败
ctx.StatusCode() 的行为细节
这个函数本质是调用 http.ResponseWriter.WriteHeader(),一旦状态码被写出,后续再调用 ctx.StatusCode() 就无效了(Go 标准库限制)。
- 它不校验状态码合法性,传入
999也不会 panic,但 HTTP 协议不认 - 推荐使用
iris.StatusXXX常量(如iris.StatusBadRequest),避免硬编码数字 - 在中间件中提前设状态码(比如鉴权失败时设 401),后续 handler 仍可覆盖——只要还没真正写响应体
和 ctx.Redirect() 混用时的坑
ctx.Redirect() 内部已调用 ctx.StatusCode()(默认 302),所以你不能再手动设状态码,否则可能冲突或被忽略。
- 错误写法:
ctx.StatusCode(301); ctx.Redirect("/new", 302)→ 实际发出的是 302,前面那句白写 - 正确做法:直接用
ctx.Redirect("/new", iris.StatusMovedPermanently) - 调用
ctx.Redirect()后必须紧跟return或ctx.StopExecution(),否则后续代码若再调ctx.StatusCode()或写响应,会触发 panic(双 WriteHeader)
最容易被忽略的是:状态码和响应体的写入时机不是原子的,尤其在嵌套中间件或 MVC Controller 中,ctx.StatusCode() 被调用的位置决定了它是否生效——它必须在任何 Write 类方法(包括 JSON、Text、Redirect)之前,且不能被后续逻辑无意覆盖。











