FastAPI状态码详解:200、404、500等使用场景

什么是HTTP状态码?

HTTP状态码是服务器向客户端返回的数字代码,用于表示请求的处理结果。比如“200”表示请求成功,“404”表示请求的资源不存在。在FastAPI中,正确设置状态码能帮助API客户端(如前端、其他服务)准确理解请求结果,是构建健壮API的基础。

FastAPI中如何设置状态码?

FastAPI提供了两种常用方式设置状态码:
1. 直接在路由函数返回时指定:通过元组 (数据, 状态码) 返回。
2. 使用HTTPException异常:抛出带有状态码和错误信息的异常(推荐用于错误场景)。

示例代码(两种方式对比):

from fastapi import FastAPI, HTTPException

app = FastAPI()

# 方式1:直接返回元组
@app.get("/hello")
def say_hello():
    return {"message": "Hello"}, 200  # 返回200 OK

# 方式2:抛出HTTPException(错误场景)
@app.get("/users/{user_id}")
def get_user(user_id: int):
    if user_id != 1:
        raise HTTPException(
            status_code=404,
            detail="User not found"
        )
    return {"user_id": user_id, "name": "Alice"}

常见状态码及使用场景

以下是初学者最常用的状态码,附简单示例帮助理解:

1. 200 OK:请求成功

场景:GET/POST/PUT等请求处理成功时返回,返回具体数据或结果。
示例:查询存在的用户信息:

fake_users_db = {1: {"name": "Alice"}, 2: {"name": "Bob"}}

@app.get("/users/{user_id}")
def get_user(user_id: int):
    if user_id in fake_users_db:
        return fake_users_db[user_id]  # 自动返回200 OK
    raise HTTPException(status_code=404, detail="User not found")  # 不存在返回404
2. 404 Not Found:资源不存在

场景:请求的资源(如ID、路径)不存在时返回,常见于GET/DELETE请求找不到目标。
示例:请求不存在的用户ID:

@app.get("/users/{user_id}")
def get_user(user_id: int):
    if user_id not in fake_users_db:
        return {"error": "User not found"}, 404  # 返回404
    return fake_users_db[user_id]
3. 500 Internal Server Error:服务器内部错误

场景:服务器代码出错、数据库连接失败等服务器端问题时返回(尽量避免暴露给用户,应捕获异常返回友好提示)。
错误示例(避免):

@app.get("/crash")
def crash():
    1 / 0  # 故意制造错误,FastAPI默认返回500(但实际应捕获!)

正确处理:用try-except捕获并返回400等具体错误:

from fastapi import HTTPException

@app.get("/divide")
def divide(a: float, b: float):
    try:
        return a / b
    except ZeroDivisionError:
        raise HTTPException(status_code=400, detail="除数不能为0")
4. 201 Created:资源创建成功

场景:POST请求创建新资源(如新增用户、商品)成功时返回,需返回新资源的信息。
示例:创建新用户:

@app.post("/users")
def create_user(new_user: dict):  # 假设接收新用户数据
    new_id = 3  # 数据库新增ID
    created_user = {"id": new_id, **new_user}
    return created_user, 201  # 返回201和创建的用户
5. 204 No Content:无内容返回

场景:DELETE/PUT请求成功但无需返回数据(如删除资源后),仅返回状态码。
示例:删除用户:

from fastapi import status

@app.delete("/users/{user_id}")
def delete_user(user_id: int):
    if user_id in fake_users_db:
        del fake_users_db[user_id]
        return {"message": "User deleted"}, status.HTTP_204_NO_CONTENT  # 204无内容
    raise HTTPException(status_code=404, detail="User not found")
6. 400 Bad Request:请求参数错误

场景:请求参数不合法(如必填字段缺失、格式错误)时返回。
示例:提交负数价格(Pydantic模型验证):

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float

@app.post("/items")
def create_item(item: Item):
    if item.price < 0:
        raise HTTPException(status_code=400, detail="价格不能为负数")
    return item, 201
7. 401 Unauthorized / 403 Forbidden
  • 401:未认证(用户未登录)。
    示例:访问需登录的接口:
  from fastapi import Depends, HTTPException
  from fastapi.security import OAuth2PasswordBearer

  oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

  async def get_current_user(token: str = Depends(oauth2_scheme)):
      if not token:  # 假设token不存在则未认证
          raise HTTPException(status_code=401, detail="未认证")

  @app.get("/profile")
  def get_profile(user=Depends(get_current_user)):
      return {"message": "已登录"}
  • 403:已认证但权限不足(如普通用户访问管理员接口)。
    示例:普通用户访问管理员接口:
  async def get_admin_role(user: dict = Depends(get_current_user)):
      if user.get("role") != "admin":
          raise HTTPException(status_code=403, detail="权限不足")

  @app.get("/admin")
  def admin_route(user=Depends(get_admin_role)):
      return {"message": "管理员数据"}

最佳实践:不同HTTP方法的状态码习惯

  • GET:查询数据,成功返回200,失败返回404(资源不存在)或400(参数错误)。
  • POST:创建资源,成功返回201,参数错误返回400。
  • PUT/PATCH:更新资源,成功返回200或204,失败返回400/404。
  • DELETE:删除资源,成功返回204,失败返回404。

总结

状态码是API的“语言”,正确使用能让客户端清晰理解请求结果。FastAPI通过status_code参数和HTTPException简化了状态码设置,初学者需重点掌握200(成功)、404(资源不存在)、500(服务器错误)、201(创建成功)、400(参数错误)等核心状态码的场景,避免因状态码混乱导致前端或下游服务错误。

(注:FastAPI自动生成的Swagger文档会显示路由的状态码,调试时可通过文档直观查看各接口的状态码定义。)

小夜