问题来源
项目中需要服务间调用,发现provider项目已经提供了对应接口,然后就使用FeignClient开始调用。结果无法正常工作,然后查看日志,发现服务间调用返回的竟然是异常信息。
{"timestamp":1554718813930,"status":406,"error":"Not Acceptable","message":"Could not find acceptable representation","path":"/xxxxUser/yyyyAuth"}
问题分析
服务提供方式比较老的服务了,相对比较稳定,当时发现对方已经提供了Rest API就直接使用,没有怀疑过服务提供方问题。然后又检查自己的参数,发现问题。然后查看HTTP 406的含义
406 Not Acceptable
请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。
除非这是一个 HEAD 请求,否则该响应就应当返回一个包含可以让用户或者浏览器从中选择最合适的实体特性以及地址列表的实体。实体的格式由 Content-Type 头中定义的媒体类型决定。浏览器可以根据格式及自身能力自行作出最佳选择。但是,规范中并没有定义任何作出此类自动选择的标准。
HTTP 406 错误 – 无法接受 (Not acceptable)
介绍
客户端(如您的浏览器或我们的 CheckUpDown 机器人)可以向 Web 服务器表明它将接受的服务器反馈数据的特征。 这是通过使用以下类型 '接受头'来完成的 :
接受:为客户端所接受的 MIME (多功能互联网邮件扩充服务) 类型。 例如,浏览器可能只接受它知道如何处理的反馈数据类型(HTML 文件, GIF 文件等)。
接受 - 字符集:为客户端所接受的字符集。
接受 - 编码:为客户端所接受的数据编码,如客户端可理解的文件格式,。
接受 - 语言:为客户端所接受的自然语言(英语,德语等)。
接受 - 范围:客户端是否接受来自网络资源的字节范围,即该资源的一部分。
如果 Web 服务器检测发现它想反馈的数据不能为客户端所接受,它则反馈一个含有 406 错误代码的报头。
我们统一约定Rest API返回的都是json格式的,因此我的强求格式也是json, 应该是该服务提供的返回结果格式不正确导致的。然后对方查看服务提供代码。果然发现,不知道什么原因这个API的返回格式竟然写的是
@PostMapping(value = "/xxxxUser/yyyyAuth", produces = "text/json;charset=UTF-8")
这个肯定是不对的。我们都是使用的 produces = “application/json;charset=UTF-8”
注意: 其他API都是 produces = “application/json;charset=UTF-8”, 唯独这API写错了。一直没有人调用,刚好单元测试也没有覆盖这个API,所以错误一致隐藏到现在。
解决办法
非常简单,将原来错误的修改为 produces = “application/json;charset=UTF-8”.
截图
截图1, 该API在通过Swagger调用时,一切正常
截图2, 该API在通过FeignClient服务间调用时才出现异常