Files
fastapi_server/README.md

3.5 KiB
Raw Permalink Blame History

py_server

这是一个 FastAPI 异步 API 项目骨架,分层方式参考了 Hyperf 项目里的 server/app

分层对应

Hyperf FastAPI 当前项目 作用
Controller/Admin app/controller/admin 接收请求,调用 service
Service/Admin app/service/admin 业务逻辑
Common/Repository app/common/repository 数据访问
Model app/model 数据模型
Middleware/Admin app/middleware/admin admin token 和权限校验
Lib/Jwt app/lib/jwt JWT 签发、解析、黑名单
Request/Admin app/request/admin 请求参数校验
Constants app/constants 状态码和业务常量
Lib/Return app/lib/response 统一返回结构

Python 里 return 是关键字,所以参考 Hyperf 的 Lib/Return 在这里命名为 lib/response

启动

.venv/bin/uvicorn app.main:app --reload

默认启动时会自动创建 SQLite 开发库,并创建一个 admin 用户:

  • username: admin
  • password: admin

本地配置可以复制:

cp .env.example .env

Admin 登录接口

登录

POST /admin/login/login
Content-Type: application/json

{
  "username": "admin",
  "password": "admin"
}

返回:

{
  "code": 0,
  "message": "success",
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "expire_at": 3600
  }
}

刷新 token

POST /admin/login/refresh
Authorization: Bearer <refresh_token>

刷新成功后会签发新的 access_tokenrefresh_token,并把旧的 refresh_token 加入黑名单,防止重复刷新。

当前 admin 用户

GET /admin/profile/current
Authorization: Bearer <access_token>

JWT 逻辑

当前实现和参考 Hyperf 项目保持同样思路:

  1. 登录成功后同时签发 access_tokenrefresh_token
  2. 普通 admin 接口只接受 access_token
  3. /admin/login/refresh 只接受 refresh_token
  4. refresh 成功后,把旧 refresh token 加入黑名单。
  5. token 会校验签名、过期时间、issuer 和 token 类型。

token 读取顺序和 Hyperf 中间件一致:

  1. Authorization: Bearer <token>
  2. token header
  3. query string: ?token=...

FastAPI 依赖注入

Controller 里这段:

service: LoginService = Depends(get_login_service)

可以理解为 FastAPI 版的 Hyperf 容器注入。

请求进来时FastAPI 会先调用 get_login_service(),把创建好的 LoginService 传给 service 参数。

get_login_service() 内部会继续组装:

  • AdminUserRepository
  • BaseTokenService
  • AdminReturn

所以 controller 只负责接收请求和调用 service。

@lru_cache 的作用

app/core/dependencies.py 里的:

@lru_cache
def get_database() -> Database:
    return Database(get_settings().database_path)

表示第一次调用时创建对象,后面再次调用时直接复用第一次创建的对象。

在这个项目里,它的作用类似 Hyperf 容器里的共享服务/单例服务。比如 JWT 黑名单必须复用同一个对象,否则旧 refresh token 加入黑名单后,下一次请求就查不到了。

测试

.venv/bin/python -m compileall app tests
.venv/bin/python -m unittest tests.test_admin_login_flow

测试覆盖:

  • admin 登录成功
  • access token 访问当前用户成功
  • refresh token 换新 token 成功
  • 旧 refresh token 复用失败
  • access token 调用 refresh 接口失败