如何在accept头字段中指定接受具有特定内容类型的多部分/相关内容类型

Gun*_*ger 5 http multipart http-headers mime-types http-accept-header

RFC 7231 - HTTP/1.1语义和内容,5.3内容协商没有定义如何指定接受具有接受头字段中的正文部分的特定内容类型的多部分/相关内容类型.

例如,如何用text/html正文部分表达对多部分/相关内容的接受

Accept: multipart/related;type=text/html
Run Code Online (Sandbox Code Playgroud)

要么

Accept: multipart/related,text/html
Run Code Online (Sandbox Code Playgroud)

如果你想为不同的html风格指定优先级?

Accept: multipart/related;type=text/html;q=0.7,
   multipart/related;type=text/html;level=1,
   multipart/related;type=text/html;level=2;q=0.4
Run Code Online (Sandbox Code Playgroud)

要么

Accept: multipart/related,text/html;q=0.7,
   text/html;level=1,
   text/html;level=2;q=0.4
Run Code Online (Sandbox Code Playgroud)

什么是对的?都?

DaS*_*rer 5

首先,HTTP是一种类似 MIME的协议,而不是符合 MIME的协议.引用RFC 7230,第2.1节:

邮件的传递格式类似于Internet邮件[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045]所使用的格式(有关HTTP和MIME邮件之间的差异,请参阅[RFC7231]的附录A).

记住这一点很重要,因为这在处理MIME内容时给了我们一些自由.

所述Accept报头是受RFC 7231,秒.5.3.2.这里描述的语法允许包含逗号分隔的媒体类型列表(参见RFC 7230,第7节),除了HTTP特定的权重参数之外,每个参数还包含任意数量的媒体类型特定参数q(参见RFC 7231,第5.3节). 1).

第3.1.1.1节讨论哪些mediatypes对于AcceptContent-Type标题有效:

HTTP 在和头字段中使用Internet媒体类型[RFC2046],以提供开放和可扩展的数据类型和类型协商.[...]互联网媒体类型应根据[BCP13]中规定的程序在IANA注册Content-TypeAccept

[BCP13]指的是RFC 6838,最终导致IANA媒体类型注册表.

值得一提的是Accept标题的语法不需要任何参数; 就HTTP规范而言,它们都是可选的.如果有必要的参数,则必须直接通过相关的mediatype:

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

multipart/relatedMIME类型本身是受RFC 2387.第3.1节明确规定了type参数的强制性.它也是单个值,而不是列表.有趣的是,HTTP规范强调了boundary参数的存在对RFC 2046第5.1.1节的重要性.从RFC 7231,第3.1.1.4节:

所有多部分类型共享一个通用语法,如[RFC2046]的第5.1.1节中所定义,并包含边界参数作为媒体类型值的一部分.

我的猜测是,作者从未想过会将多部分mediatype放入Accept标题中,这会使边界变得无用.这确实可以成为勘误的候选人(朱利安?).从技术上讲,绝对正确的方式是:

Accept: multipart/related; type=text/html; boundary=--my-top-notch-boundary-
Run Code Online (Sandbox Code Playgroud)

实际上,实现者似乎倾向于故意忽略这些要求,如本例所示.我通常不提倡反对遵循RFC,但我认为跳过boundary参数实际上是有意义的.请记住,这是在内容协商中使用的请求标头,而不是消息部分之间具有指定边界的seom实际内容的描述,我想不出请求这样的边界是合法的用例; unles你出去造成一些恶作剧.但是,你再次要求对自己进行操纵请求.不过我没有决定省略type参数.恕我直言这样做意味着type=*/*,这有效地是"我不在乎,发送任何你认为合适的东西".虽然这可能会导致响应与RFC2387完全一致,但我个人对于对返回的内容类型进行这一点控制感到不安.(旁注:您可能总是想检查回复的内容类型.2xx代码不能保证您得到了您的要求)

现在,如果您发送请求Accept: mutlipart/related, text/html,则要求指定未指定类型的几个部分或者单个HTML文档.如果您想协商内容,则需要请求multipart/related不同类型的多种变体:

Accept: multipart/related; type=text/html,
        multipart/related; type=text/plaintext
Run Code Online (Sandbox Code Playgroud)

(注意:添加了行继续以提高易读性.请注意,行继续已被弃用,不应再在HTTP上下文中使用.)

关于你的例子,我很惊讶地发现这个mediatype的语法在参数方面非常严格.情况如下:

  • 这样的Accept标题受RFC 7231,sec.5.3.2
  • 根据RFC 6838,mediatype(s)和子类型直接来自IANA媒体类型注册表
  • 参数处理如下:
    • q受RFC 7231,sec.的授权.5.3.1
    • boundary受RFC 2046的授权,sec.5.1.1
    • 剩余参数受到mediatypes各自的RFC的影响.在这种情况下,这意味着type需要,然后是可选参数startstart-info
    • 根据RFC 2046第1部分,将丢弃无法识别的参数:

      MIME实现还必须忽略其名称无法识别的任何参数.

所以,如果level是一个公认的参数(目前这甚至不是text/htmlmediatype的情况.是的,我知道它出现在多个例子中),正确的解决方案确实是这样的:

Accept: multipart/related; type=text/html; q=0.7,
        multipart/related; type=text/html; level=1,
        multipart/related; type=text/html; level=2; q=0.4
Run Code Online (Sandbox Code Playgroud)

但剥离level参数,我们归结为:

Accept: multipart/related; type=text/html; q=0.7,
        multipart/related; type=text/html,
        multipart/related; type=text/html; q=0.4
Run Code Online (Sandbox Code Playgroud)

这与以下内容相同:

Accept: multipart/related; type=text/html
Run Code Online (Sandbox Code Playgroud)


Jul*_*hke 0

实际上,它确实定义了它——它表示允许使用可选参数。如何解释它们取决于媒体类型定义,而不是 Accept 标头字段的语法。