Does HTTP content negotiation respect media type parameters

拜拜、爱过 提交于 2019-12-05 16:46:51

The relevant standard, RFC 7231 section 3.1.1.1, says the following about media-types:

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

So, Accept and Content-Type headers may contain media type parameters. It adds:

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.

That suggests that the server code that uses parameter types should pay attention to them, and not simply discard them, because for some media types they will be significant. It has to implement some smarts in whether to consider whether the media type parameters are significant.

Spring MVC 4.1.0 therefore seems to be wrong to completely ignore the parameters when doing content negotiation: the class org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor is incorrect to use org.springframework.util.MimeType.isCompatibleWith(MimeType), or that MimeType.isCompatibleWith(MimeType) method is incorrect. If you provide Spring with several HTTP message converters that differ only in the parameters of their supported media type, Spring will not reliably choose the HTTP message converter that has the media type that exactly matches the requested media type.


In section 3.1.1.5, where it describes the Content-Type header, it says:

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

As the parameters of a media type in general could vary the data format, the behaviour of Spring MVC 4.1.0 is wrong, in providing parameters that are an inaccurate description of the body of the response: the method AbstractMessageConverterMethodProcessor.getMostSpecificMediaType(MediaType, MediaType) is wrong to return the acceptType rather than the produceTypeToUse when the two types are equally specific.


However, section 3.4.1, which discusses content negotiation (Proactive Negotiation), notes:

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.

So the server is permitted to give a response that does not exactly match the media-type parameters requested, as a fall-back when it can not provide an exact match. That is, it may choose to respond with a application/vnd.example; version=1 response body, with a Content-Type: application/vnd.example; version=1 header, despite the request saying Accept: application/vnd.example; version=2, if, and only if generating a valid application/vnd.example; version=2 response would be impossible.


This apparently incorrect behaviour of Spring already has a Spring bug report, SPR-10903. The Spring developers closed it as "Works as Designed", noting

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"

The relevant spec for content negotiation in HTTP/1.1 is RFC2616, Section 14.1.

It contains the following example, relevant to your question:

Accept: text/*, text/html, text/html;level=1, */*

and gives the precedence as

1) text/html;level=1
2) text/html
3) text/*
4) */*

So I think it is safe to say that text/html;level=1 and text/html are different media types. I would also consider text/html;level=1 and text/html;level=2 as different.

So in your example I think it would be correct to respond with a 406 error and not respond with a different media type.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!