Swagger 页面上 /v1/users 的 nickname 标的是可选,客户端按文档不传,线上直接返回 400,提示 nickname 不能为空。日志里能对上时间点,这种反而好排。
文档是扫描注解生成的,DTO 上只加了非空校验注解,没有加 OpenAPI 的 required 描述,两边各说各话。字段约束和文档注解没有绑在同一个地方,改一处漏一处,时间久了没人能对上。这一点先确认清楚,后面就不用反复试。
curl -s https://api.example.com/v3/api-docs | jq '.components.schemas.User.required'
「OpenAPI 注解」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。
改完顺手把文档补一句,省得下次自己重新推一遍。
处理上按这个顺序:在 DTO 字段上同时写校验注解和 Schema 描述的 required;把生成出来的 openapi.json 存进仓库 每次发版对比差异;用契约测试跑一遍必填字段 文档和实现不一致就让构建失败;前端生成客户端时以 openapi.json 为准 不要手抄字段。
结果对不对很好判断,Swagger 页面上 nickname 显示为必填 不传时文档和实际返回的 400 一致。
