接口返回 500 但只有错误码:Content-Type 少一个字段排查全过程
一、这次的报错长什么样
昨天写脚本拉开发者社区的问答帖子列表,用的是社区前端自己调的那个接口。按接口文档的说明,请求体应该以 JSON 形式提交,所以我构造了这样的请求:
- 方法:
POST - 路径:
/rest/developer/fwdu/rest/developer/user/hdcnforumservice/v1/get-topic-list - 请求头:带
csrf - 请求体:
{"pageNo":1,"pageSize":5,"queryType":2}
返回结果是:
HTTP 500
{"error_msg":"internal error","error_code":"HD.75100001"}
error_msg 是 internal error,error_code 是 HD.75100001。除此之外没有任何别的信息——没有说哪个字段不对,没有说缺什么请求头,连「请求体解析失败」这种方向都没有。
第一反应当然是自己的参数拼错了。于是我把能换的都换了一遍:把 pageNo 从数字改成字符串、把 queryType 从 2 换成 1、把路径前缀 fwdu 换成 fwdo、把请求体里的字段删到只剩 {}。每换一次拿回来的都是同一个 HD.75100001,一模一样的响应体,一次线索都没有。
二、真正的原因
最后定位到的原因跟参数无关:请求头少了 Content-Type: application/json。
服务端按 text/plain 去解析请求体,解析 JSON 时抛异常,异常被统一包成了 internal error 加 HD.75100001。也就是说,错误码本身跟「哪个参数写错了」毫无关系,它只表示「服务端处理这个请求时内部出错了」。
我做了一个对照实验,四组请求除了 Content-Type 之外完全一致:
- A 组:不带
Content-Type,客户端默认发text/plain - B 组:
Content-Type: application/json - C 组:
Content-Type: application/json;charset=UTF-8 - D 组:
Content-Type: text/plain,显式写错
结果:
- A 组:HTTP 500,
HD.75100001 - B 组:HTTP 200,正常返回帖子列表
- C 组:HTTP 200,正常返回帖子列表
- D 组:HTTP 500,
HD.75100001
A 组和 D 组表现完全一致,B 组和 C 组表现完全一致。这说明服务端只关心 Content-Type 的主类型是不是 json,后面带不带 charset 参数无所谓;而一旦主类型不是 json,就直接落到那个统一的 500 分支里。
顺带记一下耗时:带正确 Content-Type 的请求,我连跑 3 次分别是 2117 毫秒、2074 毫秒、2090 毫秒,中位数约 2090 毫秒。这个接口本身不算快,所以后面如果遇到偶发超时,先怀疑是不是根本没走到业务逻辑。
三、这类排查还有两个坑
第一个坑:错误码会骗人。 HD.75100001 这种通用码不代表「参数非法」,它代表「服务端抛异常了」。请求体格式不对、请求头缺关键字段、路径写错落到不存在的路由,在响应里长得一模一样。所以看到这个码,别在参数值上死磕,要先怀疑「请求有没有被正确解析」。
第二个坑:错误的响应体会掩盖错误的原因。 这次真正有用的信息只有一条,就是 Content-Type,而它既不在响应里,也不在错误码的含义里。如果服务端在返回体里多带一句「请求体解析失败,请检查 Content-Type 是否为 application/json」,我大概第一次就能定位到,五个来回的盲试可以省掉。
四、我的排查顺序
后来这类问题我固定按这个顺序查,基本每次都能收敛:
- 先看 HTTP 状态码。500 配一个通用错误码,优先怀疑请求没被正确解析,而不是业务规则不满足。
- 然后核对
Content-Type。凡是请求体是 JSON,一律显式写application/json,别指望客户端默认值。这个习惯能省掉一整类问题。 - 再确认请求体是真 JSON 字符串,不是对象被隐式转成了
[object Object]。用语言自带的序列化函数打印一遍,比肉眼看更可靠。 - 最后才去调参数值。参数值写错通常会返回 400,或者返回一个能看出「哪个字段」的错误信息,不会是
internal error。
五、一点感想
排查这类问题的成本,八成不在「想不明白」,而在「错误信息不够」。
一个返回 internal error 的 500,让我花了五个来回才定位到一个请求头字段。这五个来回里,我改的每一个参数都是对的——真正错的那一项从头到尾没在参数里。
所以比起「学会猜」,我更希望服务端能把真实原因带出来。哪怕只在错误体里加一句「请求体不是合法 JSON」,收益就完全不一样了。
也欢迎有类似经历的评论区说说,你们踩过最难查的接口报错是什么样的。
- 点赞
- 收藏
- 关注作者
评论(0)