http - HTTP 内容协商是否尊重媒体类型参数

标签 http spring-mvc content-negotiation

一个 HTTP 请求可以包含一个 Accept header ,指示客户端可接受的响应媒体类型。服务器应通过提供具有与请求的媒体类型(之一)相匹配的 Content-Type 的响应来尊重请求。媒体类型可能包括参数。 HTTP 是否要求此内容协商过程遵守参数

也就是说,如果客户端请求

 Accept: application/vnd.example; version=2

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

 Content-Type: application/vnd.example; version=1

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

 Content-Type: application/vnd.example; version=2

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

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

最佳答案

相关标准,RFC 7231 section 3.1.1.1 ,关于媒体类型的说明如下:

The type/subtype MAY be followed by parameters in the form of name=value pairs.

因此,AcceptContent-Type header 可能包含媒体类型参数。它补充说:

The presence or absence of a parameter might be significant to the processing of a media-type, depending on its definition within the media type registry.

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

因此,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 消息转换器。


section 3.1.1.5 ,它描述了 Content-Type header ,它说:

The indicated media type defines both the data format and how that data is intended to be processed by a recipient

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


然而,section 3.4.1 ,其中讨论了内容协商(主动协商),注释:

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.

因此,服务器允许给出一个与请求的媒体类型参数不完全匹配的响应,作为它不能提供精确匹配时的后备匹配。也就是说,它可能会选择用 application/vnd.example 进行响应; version=1 响应主体,带有 Content-Type: application/vnd.example; version=1 header ,尽管请求说 Accept: application/vnd.example; version=2当且仅当生成有效的application/vnd.example; version=2 响应是不可能的。


Spring 的这种明显不正确的行为已经有一个 Spring 错误报告,SPR-10903 . Spring 开发人员将其关闭为“按设计工作”,并指出

I don't know any rule for comparing media types with their parameters effectively. It really depends on the media type...If you're actually trying to achieve REST versioning through media types, it seems that the most common solution is to use different media types, since their format obviously changed between versions:

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

关于http - HTTP 内容协商是否尊重媒体类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32071006/

相关文章:

asp.net - 从 ASP.NET 禁用所有浏览器的浏览器缓存

java - 如何在java中使用spring解压上传的zip文件

Eclipse 未正确部署我的 Web 应用程序

spring-mvc - Spring MVC 与 HttpMessageConverter 进行内容协商

jquery - 为什么 jQuery.ajax 在 POST 调用后遵循重定向?

c++做套接字关闭自己运行时

c# - 检查 HttpWebResponse 是否为空

java - Spring MVC 无法处理来自资源处理程序的 404?

c# - 返回 HTML 的内容协商

HTTP 内容协商/压缩 : Use Base64 with Accept-Encoding/Content-Encoding?