接口联调 / 已完成
前后端接口联调
理解接口契约、请求地址、跨域、token、分页、表单提交、错误码和联调排查顺序。
返回文章积累一句话:接口联调就是让前端发出的请求,能被后端正确接住、校验、处理,并把前端看得懂的结果返回来。
本篇学完你会什么:知道接口联调前要约定什么,怎么处理跨域、token、分页、错误码、表单提交,以及出现“前端说传了、后端说没收到”时该怎么查。
1. 接口联调到底在联什么
前端和后端就像两个人配合办事。
前端负责:
收集用户输入
组织请求参数
发送请求
展示返回结果
展示错误和 loading后端负责:
接收请求
校验参数
检查登录和权限
处理业务
读写数据库
返回结果或错误接口联调不是“请求能发出去”就完了,而是要确认每一步都对得上。
2. 先约定接口契约
接口契约就是前后端先说清楚:
| 要约定什么 | 例子 |
|---|---|
| 请求方法 | GET / POST / PUT / DELETE |
| 请求路径 | /api/v1/users |
| 请求参数 | page、page_size、keyword |
| 请求体 | username、email、role_ids |
| 返回数据 | items、total |
| 错误格式 | code、message |
| 是否要登录 | 要不要带 token |
| 需要什么权限 | user:read、user:create |
比如用户列表可以约定成:
GET /api/v1/users?page=1&page_size=20&keyword=tom
Authorization: Bearer <token>返回:
{
"items": [
{
"id": 1,
"username": "tom",
"email": "tom@example.com",
"is_active": true
}
],
"total": 1
}3. 请求地址和环境怎么处理
开发时最常见的问题是:前端请求地址写错。
建议分三层:
| 层 | 例子 | 说明 |
|---|---|---|
| 前端代码里 | request.get('/users') | 只写业务路径 |
| 请求封装里 | baseURL: '/api/v1' | 统一加 API 前缀 |
| 开发代理里 | /api -> http://localhost:8000 | 转发到后端 |
不要在每个页面里到处写:
fetch('http://localhost:8000/api/v1/users')更推荐:
request.get('/users', { params: query })这样以后从本地切到测试环境,只改请求封装或环境变量,不用全项目搜索替换。
4. 跨域是什么
跨域就是浏览器发现:
前端页面在 localhost:3000
后端接口在 localhost:8000它会问:这个前端有没有资格请求这个后端?
后端需要允许来源:
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)开发环境也可以用前端代理绕开跨域:
浏览器 -> 前端开发服务器 /api -> 后端 localhost:8000大白话:跨域不是后端接口坏了,而是浏览器在替用户把门。
5. token 怎么带
登录后拿到 token:
{
"access_token": "eyJxxx"
}前端请求拦截器统一加请求头:
request.interceptors.request.use((config) => {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});后端用依赖读取:
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
):
token = credentials.credentials
payload = decode_access_token(token)
return await get_user_by_id(int(payload["sub"]))联调时如果接口一直 401,先看浏览器 Network:
Request Headers 里有没有 Authorization
Authorization 是不是 Bearer 开头
token 有没有过期
后端 JWT_SECRET 有没有变6. 列表分页怎么对齐
前端常用:
type UserQuery = {
page: number;
page_size: number;
keyword?: string;
};后端接:
@router.get("/users")
async def list_users(
page: int = 1,
page_size: int = 20,
keyword: str | None = None,
):
...返回建议固定:
{
"items": [],
"total": 0,
"page": 1,
"page_size": 20
}不要一会儿叫 list,一会儿叫 records,一会儿叫 data。一个项目里统一就好。
7. 表单提交怎么对齐
前端表单:
type UserFormValue = {
username: string;
email: string;
password?: string;
role_ids: number[];
is_active: boolean;
};后端 Schema:
class UserCreate(BaseModel):
username: str
email: EmailStr
password: str
role_ids: list[int] = []
is_active: bool = True重点看字段名:
| 前端字段 | 后端字段 | 是否一致 |
|---|---|---|
username | username | 一致 |
roleIds | role_ids | 不一致,需要转换 |
isActive | is_active | 不一致,需要转换 |
如果前端用驼峰、后端用下划线,要么在请求前转换,要么后端 Schema 支持 alias。不要靠记忆临时猜。
8. 错误码怎么对齐
建议后端错误尽量清楚:
| HTTP 状态码 | 大白话 | 前端怎么处理 |
|---|---|---|
| 400 | 参数不对 | 显示表单错误 |
| 401 | 没登录或 token 失效 | 跳登录页 |
| 403 | 没权限 | 显示无权限 |
| 404 | 数据不存在 | 提示记录不存在 |
| 409 | 数据冲突 | 提示用户名重复 |
| 500 | 服务内部错误 | 提示稍后再试 |
前端不要只写:
请求失败最好能根据错误信息告诉用户下一步:
用户名已存在,请换一个。
登录已失效,请重新登录。
你没有删除用户的权限。9. 联调排查顺序
遇到问题时,按这条链路查:
1. 页面状态对不对
2. Network 里请求有没有发出去
3. 请求 URL、method、headers、payload 对不对
4. 后端接口有没有收到
5. 后端参数校验有没有过
6. 权限和 token 有没有过
7. 数据库查询或写入有没有成功
8. 返回格式前端能不能解析不要一上来就猜“是不是框架 bug”。多数联调问题都在 URL、字段名、token、错误格式这几处。
10. 常见错误
| 错误 | 表现 | 修正 |
|---|---|---|
| 前端 URL 写死 | 换环境就坏 | 统一 baseURL |
| 忘带 token | 后端 401 | 请求拦截器统一加 Authorization |
| 字段名不一致 | 后端收不到值 | 对齐命名或做转换 |
| 前端只看 200 | 错误体验很差 | 根据状态码分别处理 |
| 后端返回格式不统一 | 前端到处写兼容 | 统一响应契约 |
| CORS 配错 | 浏览器拦截 | 配 allow_origins 或开发代理 |
| 分页字段不统一 | 表格页码错乱 | 固定 items/total/page/page_size |
11. 联调检查清单
[ ] 接口文档里有 method、path、params、body、response
[ ] 前端请求 baseURL 统一
[ ] 本地开发代理能转发到后端
[ ] 需要登录的接口带 Authorization
[ ] 401、403、409、500 有不同处理
[ ] 列表返回 items 和 total
[ ] 表单字段名和后端 Schema 对齐
[ ] 删除、修改等危险操作有权限校验
[ ] Network 能看到真实 payload
[ ] 后端日志能查到请求和错误原因12. 总结表
| 名词 | 大白话 |
|---|---|
| 接口契约 | 前后端约好的请求和返回格式 |
| baseURL | 所有接口的统一前缀 |
| CORS | 浏览器的跨域安全检查 |
| Authorization | 放 token 的请求头 |
| payload | 前端真正发出去的数据 |
| Network | 浏览器里看请求真相的地方 |
| 401 | 没登录 |
| 403 | 没权限 |
| 409 | 数据冲突,比如用户名重复 |
上一篇建议:大白话讲解——从 0 到 1 做一个用户管理系统.md
下一篇建议:大白话讲解——后台权限系统设计.md