首页 / FastAPI 入门教程 / 响应状态码与响应头

FastAPI 入门教程

响应状态码与响应头

本教程共 50 篇 · 第 15 篇 · 更新于 2026-08-12 · 约 8 分钟阅读

FastAPIFastAPI 入门教程status_code响应头ResponseHTTP状态码

本节目标:学会在接口上设置正确的 HTTP 状态码,并掌握两种给响应加上自定义响应头、Cookie 的办法。

一个 HTTP 响应,不只是 body 里那串 JSON。它还有状态码(告诉客户端成功还是失败)和响应头(传递额外的元信息,比如令牌、内容语言)。FastAPI 让这两件事都很好操作。

15-1 用 status_code 设置状态码

status_code 是装饰器的参数。你直接传一个数字就行:

from fastapi import FastAPI

app = FastAPI()


@app.post("/items/", status_code=201)
async def create_item(name: str) -> dict:
    return {"name": name}

这样,成功创建后客户端收到的就是 201 Created,而不是默认的 200。FastAPI 会把这个码写进 OpenAPI,自动文档里也能看到。

Note

status_code 是装饰器参数(@app.post(...) 里),不是函数参数。它接收一个整数,也可以接收 Python 的 http.HTTPStatus 这种枚举值。

15-2 不必死记数字:用 status 常量

状态码的数字不好记,比如 201 是 Created,204 是无内容。FastAPI 内置了 fastapi.status 常量,配合编辑器的自动补全,敲代码更省心。

from fastapi import FastAPI, status

app = FastAPI()


@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(name: str) -> dict:
    return {"name": name}


@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int) -> None:
    return None

常用常量对照:

常量含义
status.HTTP_200_OK200请求成功(默认)
status.HTTP_201_CREATED201创建资源成功
status.HTTP_204_NO_CONTENT204成功但无内容返回
status.HTTP_400_BAD_REQUEST400请求参数错误
status.HTTP_404_NOT_FOUND404资源不存在
status.HTTP_422_UNPROCESSABLE_ENTITY422数据校验失败
Tip

fastapi.status 其实就是 Starlette 的 starlette.status,FastAPI 帮你重新导出,方便直接用。

15-3 状态码速查:三类你最常用

HTTP 状态码是三位数字,大致分几档:

  • 200–299 成功类。200 是默认的成功;201 常用于新建资源;204 表示成功但响应体为空(删除操作很合适)。
  • 300–399 重定向类,日常接口较少手动用。
  • 400–499 客户端错误类。400 通用错误,404 资源找不到,422 是 FastAPI 校验失败时自动返回的。
  • 500–599 服务器错误类,一般由框架在代码崩溃时自动返回,你很少手动设。

记住一个判断法:成功走 2xx,客户端的问题走 4xx,服务器自己的锅走 5xx。

15-4 用 Response 参数加响应头

如果你想在正常的 return 之外,顺手给响应加几个头(比如自定义 X-Process-Time),可以把 Response 声明成函数的一个参数。FastAPI 会把这个临时响应对象的头、Cookie、状态码,合并到你最终返回的数据上。

from fastapi import FastAPI, Response

app = FastAPI()


@app.get("/items/")
async def read_items(response: Response) -> dict:
    response.headers["X-Custom-Header"] = "fastapi-rocks"
    return {"items": ["苹果", "香蕉"]}

注意这里 return 的还是普通字典,响应模型(如果有的话)照常过滤。FastAPI 只是从那个 response 参数里把头”抠”出来,塞进最终响应里。你也可以在依赖里声明 Response 参数并设头,效果一样。

15-5 直接返回 Response 对象加响应头

另一种方式,是你自己构造一个 JSONResponse(或 Response)并返回,把头作为额外参数传进去。这时你完全掌控整个响应。

from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()


@app.get("/header-demo/")
async def header_demo() -> JSONResponse:
    content = {"message": "你好,世界"}
    headers = {
        "X-Web-Framework": "FastAPI",
        "Content-Language": "zh-CN",
    }
    return JSONResponse(content=content, headers=headers)

这种方式适合你想一次性决定 body、头、状态码的场景。

Note

fastapi.responses 本质上就是 Starlette 的 starlette.responses,FastAPI 重新导出方便使用。常用的 JSONResponseResponsePlainTextResponse 都从它导入。

Response 还能设置和读取 Cookie,以及手动改写状态码。下面这个例子在返回时下发一个 Cookie,并把状态码改成 202。

from fastapi import FastAPI, Response, status

app = FastAPI()


@app.get("/login/")
async def login(response: Response) -> dict:
    response.set_cookie(key="session_id", value="abc123", httponly=True)
    response.status_code = status.HTTP_202_ACCEPTED
    return {"msg": "已登录"}

set_cookie 的几个常用参数:key 是 Cookie 名,value 是值,httponly=True 让前端 JavaScript 读不到它(更安全)。response.status_code 直接赋值即可覆盖装饰器里的默认码。

Tip

/docs 文档界面里,因为浏览器用 JavaScript 发请求,Cookie 这类由浏览器底层处理的数据无法被 JS 触碰,所以你填了 Cookie 点执行也看不到效果。这不是你写错了,是浏览器的安全机制,用真实客户端(如 requests、前端 fetch)测试即可。

X- 前缀曾是自定义专有响应头的旧惯例,但 RFC 6648 已不再推荐强制使用;新设计的头可以直接起有意义的名字。如果你的头需要被浏览器里的 JavaScript 读取,还要在 CORS 配置的 expose_headers 里登记,否则前端读不到。

把前面学的串起来,下面是一个完整的登录接口:创建成功返回 201,下发会话 Cookie,并带上自定义响应头。

from fastapi import FastAPI, Response, status

app = FastAPI()


@app.post("/login/", status_code=status.HTTP_201_CREATED)
async def login(username: str, response: Response) -> dict:
    response.set_cookie(key="session_id", value="abc123", httponly=True)
    response.headers["X-Login-At"] = "now"
    response.headers["X-Web-Framework"] = "FastAPI"
    return {"username": username, "msg": "登录成功"}

这里装饰器设了默认 201Response 参数负责下发 Cookie 和两个自定义头,函数最终 return 一个普通字典。FastAPI 会把装饰器的状态码、Response 参数上的头和 Cookie,与返回的字典合并成同一个响应,客户端一次拿到全部信息。

Note

如果你直接 return JSONResponse(...) 这样的 Response 对象,装饰器的 status_codeResponse 参数上设置的头/Cookie 就不会再自动合并——你得自己在 JSONResponse 里写全。所以上面的例子选择 return 字典,让框架帮你合并。

Tip

为什么状态码对前端很重要?前端常根据状态码决定下一步:200/201 走成功逻辑,401 跳登录页,404 弹”资源不存在”,4xx 显示校验提示,5xx 提示”服务器开小差了”。码设错了,前端分支就乱了,所以别偷懒都用 200。

想确认接口返回的状态码和头是否正确,可以用命令行工具 curl 验证。比如请求登录接口后,加上 -i 参数就能看到完整的响应行、响应头和状态码,不需要打开浏览器。平时调试接口,curl 和 FastAPI 自带的 /docs 界面配合着用,效率很高。

15-8 小结

状态码和响应头是 HTTP 响应的重要组成:

  • 用装饰器的 status_code 设默认状态码,配合 fastapi.status 常量更稳妥。
  • 创建资源用 201,删除用 204,查询用 200,找不到用 404
  • 想顺带加头或 Cookie,声明一个 Response 参数,操作它后再正常 return
  • 想完全掌控响应,就自己 return JSONResponse(content=..., headers=...)
  • Response 还能 set_cookie(...) 和改 status_code,实现下发 Cookie 与动态状态码。

把这些用熟,你返回的每个响应都会更规范、更专业。