14 KiB
14 KiB
API客户端
**本文档引用的文件** - [frontend/lib/api.ts](file://frontend/lib/api.ts) - [frontend/lib/auth.ts](file://frontend/lib/auth.ts) - [frontend/app/(auth)/login/page.tsx](file://frontend/app/(auth)/login/page.tsx) - [frontend/app/(dashboard)/dashboard/queries/page.tsx](file://frontend/app/(dashboard)/dashboard/queries/page.tsx) - [frontend/components/providers.tsx](file://frontend/components/providers.tsx) - [backend/app/main.py](file://backend/app/main.py) - [backend/app/api/auth.py](file://backend/app/api/auth.py) - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/api/deps.py](file://backend/app/api/deps.py) - [backend/app/services/auth.py](file://backend/app/services/auth.py) - [backend/app/schemas/auth.py](file://backend/app/schemas/auth.py) - [backend/app/config.py](file://backend/app/config.py) - [backend/requirements.txt](file://backend/requirements.txt)目录
简介
本文件面向前端工程师与全栈开发者,系统性阐述本项目的API客户端实现与REST封装设计。内容涵盖:
- 请求配置与响应处理机制
- 错误处理、重试机制与超时控制
- 请求/响应拦截器与中间件模式
- API版本管理、URL构建与参数序列化
- 认证头自动添加、状态码处理与错误消息格式化
- 最佳实践、性能优化与调试技巧
项目结构
前端通过统一的API模块封装所有后端接口,采用按功能域分层组织:
- 前端API模块:集中定义基础URL、通用请求函数与各业务域方法
- 认证模块:集成NextAuth,负责登录态与JWT令牌流转
- 页面组件:在需要鉴权的页面中调用API模块进行数据读写
- 后端FastAPI:提供/v1版本的REST接口,统一CORS与路由前缀
graph TB
subgraph "前端"
UI["页面组件<br/>登录页/查询页"]
API["API模块<br/>api.ts"]
AUTH["认证模块<br/>auth.ts"]
end
subgraph "后端"
MAIN["应用入口<br/>main.py"]
CORS["CORS中间件"]
ROUTER_AUTH["路由: /api/v1/auth/*"]
ROUTER_QUERIES["路由: /api/v1/queries/*"]
ROUTER_CITATIONS["路由: /api/v1/citations/*"]
ROUTER_REPORTS["路由: /api/v1/reports/*"]
end
UI --> API
AUTH --> API
API --> MAIN
MAIN --> CORS
MAIN --> ROUTER_AUTH
MAIN --> ROUTER_QUERIES
MAIN --> ROUTER_CITATIONS
MAIN --> ROUTER_REPORTS
图表来源
章节来源
核心组件
- 基础URL与请求封装
- 前端通过NEXT_PUBLIC_API_URL环境变量配置后端基地址,默认本地8000端口
- 统一的fetchWithAuth函数负责:
- 自动注入Content-Type与Authorization头(若提供token)
- 检查res.ok并解析JSON;非2xx时抛出带错误详情的异常
- 返回解析后的JSON数据
- 业务域API对象
- 提供auth、queries、citations、reports四个命名空间的方法
- 所有方法均以/v1为版本前缀,遵循REST风格
- 支持查询参数拼接与JSON体序列化
章节来源
架构总览
下图展示从前端调用到后端路由的完整链路,包括认证中间件与CORS策略。
sequenceDiagram
participant C as "客户端浏览器"
participant F as "前端API模块<br/>api.ts"
participant S as "NextAuth会话<br/>auth.ts"
participant A as "后端应用<br/>main.py"
participant D as "依赖注入<br/>deps.py"
participant H as "认证路由<br/>auth.py"
participant Q as "查询路由<br/>queries.py"
C->>S : "触发登录/获取会话"
S->>F : "调用api.auth.login(...)"
F->>A : "POST /api/v1/auth/login"
A->>D : "OAuth2密码流校验"
D->>H : "调用服务层验证用户"
H-->>A : "返回JWT令牌"
A-->>F : "返回TokenResponse(JSON)"
F-->>S : "返回access_token"
S-->>C : "更新会话状态"
C->>F : "调用api.queries.list(access_token)"
F->>A : "GET /api/v1/queries"
A->>D : "校验JWT并解析当前用户"
D-->>A : "返回当前用户"
A->>Q : "调用查询服务"
Q-->>A : "返回查询列表"
A-->>F : "返回查询列表(JSON)"
F-->>C : "返回数据"
图表来源
- frontend/lib/api.ts:23-57
- frontend/lib/auth.ts:5-55
- backend/app/main.py:38-42
- backend/app/api/deps.py:16-42
- backend/app/api/auth.py:22-37
- backend/app/api/queries.py:15-23
详细组件分析
前端API模块(请求封装与拦截器)
- 版本与URL构建
- 基于NEXT_PUBLIC_API_URL拼接/v1路径,确保版本一致性
- 查询参数通过字符串拼接传入,如citations/list(params)
- 请求拦截器
- 在fetchWithAuth内统一设置Content-Type与Authorization头
- 支持外部传入自定义headers并合并
- 响应拦截器
- res.ok检查与JSON解析
- 非2xx时从响应体提取detail或回退为HTTP状态描述,并抛出错误
- 中间件模式
- 通过API对象的命名空间体现:auth/queries/citations/reports
- 每个方法内部复用fetchWithAuth,形成“中间件式”的统一处理链
flowchart TD
Start(["进入 fetchWithAuth"]) --> MergeHeaders["合并默认与自定义头部"]
MergeHeaders --> AddAuth{"是否提供token?"}
AddAuth --> |是| SetBearer["设置Authorization: Bearer ..."]
AddAuth --> |否| SkipAuth["跳过认证头"]
SetBearer --> Fetch["执行fetch(拼接API_BASE + url)"]
SkipAuth --> Fetch
Fetch --> Ok{"res.ok?"}
Ok --> |否| ParseErr["尝试解析JSON错误体"]
ParseErr --> Throw["抛出错误(detail或HTTP状态)"]
Ok --> |是| ParseJSON["res.json()"]
ParseJSON --> Return["返回解析结果"]
图表来源
章节来源
认证流程与会话管理
- 登录页通过NextAuth的credentials提供者发起登录
- 授权回调中,若返回access_token则写入JWT与会话
- 后续页面通过useSession获取accessToken并传递给API模块
sequenceDiagram
participant L as "登录页<br/>login/page.tsx"
participant N as "NextAuth<br/>auth.ts"
participant A as "后端认证<br/>auth.py"
participant S as "会话存储"
L->>N : "signIn('credentials', {email,password})"
N->>A : "POST /api/v1/auth/login"
A-->>N : "TokenResponse(JSON)"
N->>S : "写入JWT与用户信息"
N-->>L : "登录成功/失败"
图表来源
章节来源
查询管理页面(鉴权与数据加载)
- 仅当session.accessToken存在时才加载数据,避免未授权请求
- 调用api.queries.list获取列表,错误时显示友好提示
- 新增/编辑/删除均通过对应API方法完成,最终刷新列表
sequenceDiagram
participant P as "查询页<br/>queries/page.tsx"
participant S as "会话<br/>useSession"
participant A as "API模块<br/>api.ts"
participant R as "后端路由<br/>queries.py"
P->>S : "读取accessToken"
S-->>P : "返回token"
P->>A : "api.queries.list(token)"
A->>R : "GET /api/v1/queries"
R-->>A : "返回查询列表(JSON)"
A-->>P : "返回数据"
P-->>P : "渲染表格/错误处理"
图表来源
- frontend/app/(dashboard)/dashboard/queries/page.tsx:96-113
- frontend/lib/api.ts:37-45
- backend/app/api/queries.py:15-23
章节来源
- frontend/app/(dashboard)/dashboard/queries/page.tsx:1-461
- frontend/lib/api.ts:23-57
- backend/app/api/queries.py:1-86
后端路由与中间件
- 应用入口统一注册CORS中间件与路由前缀
- 认证与查询等路由分别定义,使用Depends注入数据库与当前用户
- 依赖模块OAuth2PasswordBearer配合JWT校验,确保受保护资源访问
graph TB
M["应用入口<br/>main.py"] --> C["CORS中间件"]
M --> R1["/api/v1/auth/*"]
M --> R2["/api/v1/queries/*"]
M --> R3["/api/v1/citations/*"]
M --> R4["/api/v1/reports/*"]
R2 --> D["依赖注入<br/>deps.py"]
D --> U["当前用户校验"]
图表来源
章节来源
依赖分析
- 前端依赖
- Next.js、NextAuth用于SSR/CSR会话管理
- TypeScript类型约束保证API调用参数安全
- 后端依赖
- FastAPI提供路由与中间件能力
- SQLAlchemy异步ORM、Redis、APScheduler用于数据与任务
- Pydantic/JWT用于数据校验与令牌签发
graph TB
subgraph "前端"
N["Next.js"]
NA["NextAuth"]
TS["TypeScript"]
API["API模块"]
end
subgraph "后端"
FA["FastAPI"]
SA["SQLAlchemy"]
RD["Redis"]
AP["APScheduler"]
PJ["Pydantic/JWT"]
end
API --> FA
NA --> FA
FA --> SA
FA --> RD
FA --> AP
FA --> PJ
图表来源
章节来源
性能考虑
- 请求合并与去抖
- 对频繁触发的列表加载,可在组件侧引入防抖/节流,减少不必要的网络请求
- 缓存策略
- 对只读列表数据可采用内存缓存或React Query等缓存库,设置合理的TTL与失效策略
- 并发控制
- 使用信号量限制并发请求数,避免雪崩效应
- 传输优化
- 尽量使用JSON序列化,避免大对象重复传输;必要时启用gzip压缩(由后端CORS与服务器配置决定)
- 会话与令牌
- 利用JWT短小特性,避免携带冗余信息;结合后端配置合理设置过期时间
故障排查指南
- 常见错误与定位
- 401未授权:检查Authorization头是否正确设置;确认JWT未过期
- 403禁止访问:核对当前用户权限与资源所有权
- 404未找到:核对URL路径与UUID参数
- 500服务器错误:查看后端日志与数据库连接状态
- 错误处理机制
- 前端:fetchWithAuth在非2xx时解析响应体中的detail字段,作为用户可见错误信息
- 后端:路由层使用HTTPException返回标准错误体,包含状态码与详细信息
- 调试技巧
- 开启浏览器网络面板,观察请求头与响应体
- 在NextAuth回调中打印token与用户信息,确认会话状态
- 在API模块增加日志开关,输出URL、方法与关键参数
- 使用curl或Postman直接调用后端接口,排除前端逻辑干扰
章节来源
结论
本项目的API客户端采用简洁而一致的设计:统一的请求封装、明确的版本前缀、基于JWT的认证与严格的错误处理。通过NextAuth与FastAPI的协作,实现了前后端一致的会话与路由体验。建议在生产环境中进一步增强超时控制、重试机制与缓存策略,以提升稳定性与用户体验。
附录
API版本管理与URL构建
- 版本前缀:/api/v1
- 路由前缀:/api/v1/{domain}
- 参数序列化:
- 查询参数:字符串拼接
- 请求体:JSON.stringify
章节来源
认证头自动添加与状态码处理
- 自动添加:Authorization: Bearer {token}
- 状态码处理:res.ok检查;非2xx抛错
- 错误消息格式化:优先使用响应体中的detail字段
章节来源
请求拦截器与中间件模式
- 请求拦截器:在fetchWithAuth内统一设置头部与合并自定义头
- 响应拦截器:统一解析JSON与错误处理
- 中间件模式:API对象按领域划分,每个方法复用统一处理链
章节来源
最佳实践与性能优化
- 会话驱动:仅在accessToken存在时发起受保护请求
- 错误显式:在UI层展示用户可理解的错误信息
- 并发控制:限制同时进行的请求数量
- 缓存策略:对只读数据进行本地缓存与失效管理
章节来源