HTTP内容协商是否遵循媒体类型参数

Rae*_*ald 4 http spring-mvc content-negotiation

HTTP请求可以包括Accept标头,指示客户端将被接受的响应的媒体类型.服务器应通过提供Content-Type与所请求的媒体类型匹配(一个)的响应来兑现请求.媒体类型可以包括参数.HTTP是否要求此内容协商过程遵守参数

也就是说,如果客户请求

 Accept: application/vnd.example; version=2
Run Code Online (Sandbox Code Playgroud)

(此处version参数的值为2),服务器可以提供媒体类型application/vnd.example; version=1,但不是application/vnd.example; version=2,服务器是否可以提供响应

 Content-Type: application/vnd.example; version=1
Run Code Online (Sandbox Code Playgroud)

服务器是否可以提供标记的响应

 Content-Type: application/vnd.example; version=2
Run Code Online (Sandbox Code Playgroud)

但是对于实际被编码为媒体类型的响应的主体application/vnd.example; version=1?也就是说,对于响应的媒体类型的参数是对响应主体的不准确描述?

在进行内容协商时,Spring MVC 4.1.0似乎不尊重媒体类型参数,并且给出响应的媒体类型的参数对响应主体的不准确描述的响应.这似乎是因为该org.springframework.util.MimeType.isCompatibleWith(MimeType)方法不检查MimeType对象的参数.

Rae*_*ald 5

相关标准RFC 7231第3.1.1.1节说明了以下关于媒体类型的内容:

类型/子类型可以后跟name = value对形式的参数.

所以,AcceptContent-Type头可能包含媒体类型参数.它补充说:

参数的存在或不存在对于媒体类型的处理可能是重要的,这取决于媒体类型注册表中的定义.

这表明使用参数类型的服务器代码应该关注它们,而不是简单地丢弃它们,因为对于某些媒体类型它们是重要的.它必须在是否考虑媒体类型参数是否重要时实现一些智能.

因此,Spring MVC 4.1.0在进行内容协商时完全忽略参数似乎是错误的:类org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor使用不正确org.springframework.util.MimeType.isCompatibleWith(MimeType),或者该MimeType.isCompatibleWith(MimeType)方法不正确.如果为Spring提供多个HTTP消息转换器,这些转换器仅在其支持的媒体类型的参数上有所不同,则Spring将无法可靠地选择具有与所请求的媒体类型完全匹配的媒体类型的HTTP消息转换器.


3.1.1.5节中,它描述了Content-Type标题,它说:

指示的媒体类型定义数据格式以及收件人要如何处理该数据

由于媒体类型的参数通常可能会改变数据格式,因此Spring MVC 4.1.0的行为是错误的,在提供对响应主体的描述不准确的参数时:AbstractMessageConverterMethodProcessor.getMostSpecificMediaType(MediaType, MediaType)返回的方法是错误的acceptType而不是在produceTypeToUse这两种类型时,同样具体.


但是,讨论内容协商(主动协商)的第3.4.1节指出:

用户代理不能依赖主动协商偏好,因为原始服务器可能不会对所请求的资源实施主动协商,或者可能决定发送不符合用户代理偏好的响应优于发送406(不可接受的)回应.

因此,服务器允许给不响应正好符合要求的媒体类型的参数,如回退时,它不能提供精确匹配.也就是说,它可以选择响应具有标题的application/vnd.example; version=1响应主体,Content-Type: application/vnd.example; version=1尽管请求说Accept: application/vnd.example; version=2,如果,并且仅当生成有效application/vnd.example; version=2响应是不可能的时候.


这种明显不正确的Spring行为已经有了一个Spring bug报告,SPR-10903.春季开发者将其关闭为"按设计工作",注意到

我不知道有效地将媒体类型与其参数进行比较的任何规则.这实际上取决于媒体类型......如果你真的试图通过媒体类型实现REST版本控制,似乎最常见的解决方案是使用不同的媒体类型,因为它们的格式在版本之间明显改变:

  • " application/vnd.spring.foo.v1+json"
  • " application/vnd.spring.foo.v2+json"