我觉得 Accept 字段就是干这个的,所以应该以 Accept 为准,比如浏览器给的 Accept 为 textPlain,application/json.
对于这个 Accept 来说,我们的 SpringBoot 应用默认是反了 textPlain 格式,导致请求方报错(对方要 json 格式)。
我认为这个问题应该让请求方把 Accept 里的 textPlain 去掉来解决。
但是领导认为接口反什么格式应该是跟请求方通过其他方式(口头)约定好的,不应该要求请求方传指定的 Accpet ,说他搞了好多年没有要求请求方必须传什么 Accept 的,这就导致我要去改 Spring 的 messageConverts 一系列的东西来固定接口的响应格式。
所以来问下大家,标准的做法是什么?
1
yinmin 2023-11-14 21:47:58 +08:00 via iPhone
你领导说的没错
|
2
GTim 2023-11-14 21:48:11 +08:00 1
建议听你领导的,省事。你知道可以这么做即可
|
3
hallDrawnel 2023-11-14 22:07:51 +08:00
本身 accept 就是告诉服务端客户端期望返回什么格式的,你的理解没有问题。但实践上来说,只响应一种稳定的格式会剩下很多麻烦,返回多种格式的情况也不是那么常见。然后又是你 leader 说的,建议听 leader 的。
|
4
pigspy 2023-11-14 22:08:11 +08:00
从 HTTP 协议的标准来看你的说法不错
但是如果你们的接口仅限于内部调用的话,不在乎 Accept 的格式约束也没啥问题 |
5
dumbbell5kg OP 了解
|
6
monstervivi 2023-11-14 22:30:04 +08:00
HTTP 响应 Body ,当然是以 Request Header 中的 Accept 字段来准 ,这就是 HTTP 规范呀。
而且 Spring Web 处理响应 Body 就是按照 Accept 字段来分不同逻辑来处理。 参考 [AbstractMessageConverterMethodProcessor#writeWithMessageConverters]( https://github.com/spring-projects/spring-framework/blob/main/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java#L224C1-L224C1) 连 Spring 都是按此来作为标准,所以我认为这就是标准做法。 |
7
tool2d 2023-11-14 22:45:21 +08:00 via Android
昨天对接讯飞大模型,让他不要 accpet ,但是挡不住写服务器的野路子,只有一种 text/event 返回格式。
|
8
monstervivi 2023-11-14 22:55:03 +08:00
不过如果要修改,应该也不用修改 Spring 的 MessageConverter 吧?
@RequestMapping 注解,可以加上 consumes 值呀,例如: @GetMapping(value = "x" consumes = "*/*") |
9
xmumiffy 2023-11-14 22:58:34 +08:00 via Android
按照标准来,又想只返回 JSON ,那可以检测到非期望的 Accept 就返回 406
|
10
monstervivi 2023-11-14 23:05:06 +08:00
@monstervivi
修正: 应该是加上 produces ,例如 @GetMapping(value = "x", produces = "application/json;charset=UTF-8") |
11
leonshaw 2023-11-15 00:49:19 +08:00
听领导的。如果接口支持 text/plain ,那根据客户端传入的 Accept 选择 text/plain ,没问题。但领导的意思的是,服务端根本就不应该支持 text/plain ,接口应当约定一种固定格式,这个时候就应该忽略 Accept 头。
RFC 9110 12.1. Proactive Negotiation A user agent cannot rely on proactive negotiation preferences being consistently honored, since the origin server might not implement proactive negotiation for the requested resource or might decide that sending a response that doesn't conform to the user agent's preferences is better than sending a 406 (Not Acceptable) response. |
12
IvanLi127 2023-11-15 01:03:36 +08:00 via Android
首先我认为你的领导在狡辩,你明明是要求请求方不要传错误的 Accept 的值,他却说你是要求对方传 application/json 。乱调接口不解决,解决正常实现只有在特殊情况下适用。
不过你的领导结论是对的,程序不要输出预期以外的东西,他表面再想要 text 也不给他返。 反正他是领导,他说啥就是啥,要是我,说清楚这样做的后果是啥,然后听领导的决定执行。。。要是可以的话,我会给传那个 Accept 的请求返 400 的空响应。 |
13
chairuosen 2023-11-15 01:33:29 +08:00
协议标准跟工程实践的区别
|
14
xuanbg 2023-11-15 01:33:29 +08:00
标准的做法就是提供一种固定的数据格式,Accept 什么的,暂不支持。哈哈哈
|
15
dumbbell5kg OP @monstervivi 接口太多了,得调整 spring 的默认行为
|
16
dumbbell5kg OP @leonshaw 这里的 user agent 是浏览器吧,那这段话的意思是浏览器不能指望服务器遵守 accept 字段的规则?
|
17
lzrainchen 2023-11-15 10:28:49 +08:00
你说的这个标准术语叫 内容协商( ContentNegotiation ),Spring MVC 其实已经帮你做好了,可以查询一下相关信息
|
18
julyclyde 2023-11-15 11:39:39 +08:00
虽然你是对的,但不要“你觉得”
标准写啥样就是啥样 |
19
flyingghost 2023-11-15 14:59:30 +08:00
按规范做,是一种良好编程实践。
你可以指望你和你们的合作公司互相约好了“当你表面上说'不要'的时候,实际上你说的是'要'”。这时候不按规范是可接受的,沟通成本和开发成本都可控。 但你不能指望 github 开放它的 API 的时候和所有的潜在调用者做这样的沟通。于是使用现有共同认可的标准是最经济的做法。 但各种头本身就是一种“协商”机制。包括 content-type 协商,包括缓存协商。 它可以实现为“我期望最好是 xxxxx”,而不是“我要求一定是 xxxxx”。 例如,客户端可以写他请求 text/plain, application/json ,服务端可以实现为我尊重你的选择,尽可能匹配你的需求,如果找不到,fallback 到默认值 json 并返回。 这也为未来“可能”的扩展开放。 例如,昨天客户端说我需要 text/plain, application/xml ,服务端说对不起我只有 json 。 今天服务端进化了,提供了 json 和 xml 两种序列化方法,同样的请求今天就可以按用户需求提供 xml 响应。 至于这样的“扩展”会不会发生,也许这辈子都不会有。但至少它今天既满足了标准拥抱了变化,又满足了你 leader 的要求。 |
20
julyclyde 2023-11-15 18:05:49 +08:00
|