如何在接受头字段中指定接受特定内容类型的multipart/related内容类型。

7

RFC 7231 - HTTP/1.1 Semantics and Content, 5.3 内容协商没有定义如何在接受头字段中指定特定内容类型的multipart/related内容类型的正文部分。

例如,如何表示接受具有text/html正文部分的multipart/related内容。

Accept: multipart/related;type=text/html

或者

Accept: multipart/related,text/html

如果你想为不同的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

或者

Accept: multipart/related,text/html;q=0.7,
   text/html;level=1,
   text/html;level=2;q=0.4

什么是正确的?两者都是吗?

第二个选项是受 https://www.w3.org/Protocols/HTTP/Object_Headers.html 启发的:
"Content-Type: : 多部分类型 MIME 提供了许多“多部分”类型。这些是将几个主体部分封装在一个消息中。在 HTTP 中,只有在客户端指示接受(使用 Accept:)多部分类型和每个组成主体部分的内容类型时,才可以返回多部分类型。 与 MIME 不同,主体部分(可能)包含 HTTP 元信息头字段,这些字段是重要的。"
- Gunter Zeilinger
2个回答

9

首先,HTTP是一种类似MIME的协议,而不是符合MIME标准的协议。引用RFC 7230, section 2.1中的话:

消息传递的格式类似于Internet邮件[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045](请参见[RFC7231]的附录A以了解HTTP和MIME消息之间的区别)。

这一点很重要,因为在处理MIME内容时,我们有一些自由。

"

Accept头部受RFC 7231,第5.3.2节的约束。在那里描述的语法允许一个由逗号分隔的媒体类型列表(请参见RFC 7230,第7节),每个媒体类型具有任意数量的媒体类型特定参数,除了HTTP特定的权重参数q(请参见RFC 7231,第5.3.1节)。

第3.1.1.1节讨论了哪些媒体类型被认为是AcceptContent-Type头部的有效类型:

"
HTTP使用Internet媒体类型[RFC2046]Content-TypeAccept头字段中,以提供开放和可扩展的数据类型和类型协商。...应根据[BCP13]中定义的程序向IANA注册Internet媒体类型。
[BCP13]是指RFC 6838,最终导致IANA媒体类型注册表。值得一提的是,Accept头的语法不需要存在任何参数;就HTTP规范而言,它们都是可选的。如果有必要的参数,则必须由相关媒体类型直接指定:

参数的存在或缺失可能对媒体类型的处理具有重要意义,这取决于其在媒体类型注册表中的定义。

multipart/related MIME类型本身受到RFC 2387的约束。 其中第3.1节明确规定type参数是强制性的。 它也是一个单值,而不是一个列表。有趣的是,HTTP规范强调了boundary参数的存在重要性,而非RFC 2046,第5.1.1节。 来自RFC 7231,第3.1.1.4节

所有多部分类型都共享一种通用语法,如[RFC2046]的第5.1.1节所定义,并将边界参数作为媒体类型值的一部分。

我猜作者们从未想过有人会在 Accept 头部中放置多部分媒体类型,这将使边界无用。这可能确实是勘误表的候选项(Julian?)。因此,在技术上,请求这个的绝对正确™ 的方法是:
Accept: multipart/related; type=text/html; boundary=--my-top-notch-boundary-

实际上,实现者似乎倾向于故意忽略这些要求,正如this example所示。我通常不主张违反RFC,但我认为在这里跳过boundary参数实际上是有道理的。请记住,这是用于内容协商的请求头,而不是具有指定消息部分之间边界的某些实际内容的描述,我无法想象请求这样的边界是合法的用例;除非你想制造一些麻烦。但是再次,您正在为自己请求操纵后的请求。不过,我对省略type参数持有观望态度。在我看来,这样做会暗示type=*/*,这实际上是“我不在乎,请发送任何你认为合适的内容。”虽然这可能会导致完全符合RFC2387的响应,但我个人对返回的内容类型控制得太少感到不安。(顺便说一句:您可能始终希望检查响应的内容类型。 2xx代码不能保证您得到了所请求的内容)
现在,如果您发送一个带有Accept: mutlipart/related, text/html的请求,您要么请求未指定类型的多个部分,要么请求单个HTML文档。如果您想协商内容,您需要请求不同类型的multipart/related的几个变化。
Accept: multipart/related; type=text/html,
        multipart/related; type=text/plaintext

(注:为了提高可读性,添加了换行符。请注意,行继承已被弃用,在HTTP上下文中不应再使用。)
关于您的示例,我很惊讶地发现,当涉及参数时,这种媒体类型的语法非常严格。情况如下:
  • Accept头部由RFC 7231第5.3.2节规范,媒体类型和子类型直接来自于IANA媒体类型注册表,符合RFC 6838标准。
  • 参数处理如下:
    • q受RFC 7231第5.3.1节的授权。
    • boundary受RFC 2046第5.1.1节的授权。
    • 其余参数受到相应媒体类型的RFC规范的约束。在这种情况下,需要type,然后是可选的参数startstart-info
    • 未被识别的参数应该被丢弃,根据RFC 2046, section 1

MIME实现也必须忽略任何它们不认识的参数。

因此,如果 level 是一个已识别的参数(目前甚至{{link1: text / html mediatype}}都不是这种情况。是的,我知道它出现在多个示例中),正确的解决方案确实是这样的:
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

但是如果去掉level参数,我们只剩下这个:

Accept: multipart/related; type=text/html; q=0.7,
        multipart/related; type=text/html,
        multipart/related; type=text/html; q=0.4

这在语义上与以下内容相同:

Accept: multipart/related; type=text/html

我认为RFC 2387没有澄清我的问题:它并不是针对HTTP“接受”头字段中使用multipart/related而编写的,如果您认为您已经/可以将其文字照搬到HTTP“接受”头字段中,您还必须指定也是_强制性的_boundary参数(参见RFC 2046,多部分媒体类型的通用语法),这对我来说听起来不合理。 - Gunter Zeilinger
没有任何一份RFC明确讨论了在HTTP“Accept”头字段中使用“multipart”媒体类型的用法。你可以争辩说,它们不应该与其他媒体类型有所不同。但是-如前所述-如果你争辩,你必须为“multipart/related”提供一个“type”参数,因为在RFC 2387中它被指定为_强制性的_,你还必须解释为什么你不需要为所有“multipart”媒体类型在RFC 2046中指定的_mandatory_提供“boundary”参数。 - Gunter Zeilinger
到目前为止,我只找到了一份(相当古老的)文件,其中明确讨论了在HTTP“ Accept”头字段中使用multipart媒体类型。只是想知道是否有其他人发现更多相关信息。 - Gunter Zeilinger
@GunterZeilinger 我刚刚更新了我的回答并进行了一些澄清。 - DaSourcerer

0

实际上,它确实定义了 -- 它说允许可选参数。这些参数的解释取决于媒体类型定义,而不是 Accept 标头字段的语法。


但是如何区分 multipart/related 的参数和正文部分内容类型的参数(例如 text/html;level=1)在表达式 multipart/related;type=text/html;level=1 中? - Gunter Zeilinger
@JulianReschke,你能看一下我的回答吗?RFC 7231,第3.1.1.4节可能有一些勘误。 - DaSourcerer
没时间了,感谢你的研究。如果你认为有需要修正的地方,请务必发送邮件到HTTP WG的邮件列表。 - Julian Reschke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接