# 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`。 ## 启动 ```bash .venv/bin/uvicorn app.main:app --reload ``` 默认启动时会自动创建 SQLite 开发库,并创建一个 admin 用户: - username: `admin` - password: `admin` 本地配置可以复制: ```bash cp .env.example .env ``` ## Admin 登录接口 ### 登录 ```http POST /admin/login/login Content-Type: application/json { "username": "admin", "password": "admin" } ``` 返回: ```json { "code": 0, "message": "success", "data": { "access_token": "...", "refresh_token": "...", "expire_at": 3600 } } ``` ### 刷新 token ```http POST /admin/login/refresh Authorization: Bearer ``` 刷新成功后会签发新的 `access_token` 和 `refresh_token`,并把旧的 `refresh_token` 加入黑名单,防止重复刷新。 ### 当前 admin 用户 ```http GET /admin/profile/current Authorization: Bearer ``` ## JWT 逻辑 当前实现和参考 Hyperf 项目保持同样思路: 1. 登录成功后同时签发 `access_token` 和 `refresh_token`。 2. 普通 admin 接口只接受 `access_token`。 3. `/admin/login/refresh` 只接受 `refresh_token`。 4. refresh 成功后,把旧 refresh token 加入黑名单。 5. token 会校验签名、过期时间、issuer 和 token 类型。 token 读取顺序和 Hyperf 中间件一致: 1. `Authorization: Bearer ` 2. `token` header 3. query string: `?token=...` ## FastAPI 依赖注入 Controller 里这段: ```python 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` 里的: ```python @lru_cache def get_database() -> Database: return Database(get_settings().database_path) ``` 表示第一次调用时创建对象,后面再次调用时直接复用第一次创建的对象。 在这个项目里,它的作用类似 Hyperf 容器里的共享服务/单例服务。比如 JWT 黑名单必须复用同一个对象,否则旧 refresh token 加入黑名单后,下一次请求就查不到了。 ## 测试 ```bash .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 接口失败