首先,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节讨论了哪些媒体类型被认为是Accept
和Content-Type
头部的有效类型:
"
HTTP使用Internet媒体类型
[RFC2046]在
Content-Type
和
Accept
头字段中,以提供开放和可扩展的数据类型和类型协商。...应根据
[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
实际上,实现者似乎倾向于故意忽略这些要求,正如
this example所示。我通常不主张违反RFC,但我认为在这里跳过
boundary
参数实际上是有道理的。请记住,这是用于内容协商的请求头,而不是具有指定消息部分之间边界的某些实际内容的描述,我无法想象请求这样的边界是合法的用例;除非你想制造一些麻烦。但是再次,您正在为自己请求操纵后的请求。不过,我对省略
type
参数持有观望态度。在我看来,这样做会暗示
type=*/*
,这实际上是“我不在乎,请发送任何你认为合适的内容。”虽然这可能会导致完全符合RFC2387的响应,但我个人对返回的内容类型控制得太少感到不安。(顺便说一句:您可能始终希望检查响应的内容类型。 2xx代码不能保证您得到了所请求的内容)
现在,如果您发送一个带有
Accept: mutlipart/related, text/html
的请求,您要么请求未指定类型的多个部分,要么请求单个HTML文档。如果您想协商内容,您需要请求不同类型的
multipart/related
的几个变化。
Accept: multipart/related
multipart/related
(注:为了提高可读性,添加了换行符。请注意,行继承已被
弃用,在HTTP上下文中不应再使用。)
关于您的示例,我很惊讶地发现,当涉及参数时,这种媒体类型的语法非常严格。情况如下:
Accept
头部由RFC 7231第5.3.2节规范,媒体类型和子类型直接来自于IANA媒体类型注册表,符合RFC 6838标准。
- 参数处理如下:
q
受RFC 7231第5.3.1节的授权。
boundary
受RFC 2046第5.1.1节的授权。
- 其余参数受到相应媒体类型的RFC规范的约束。在这种情况下,需要
type
,然后是可选的参数start
和start-info
。
- 未被识别的参数应该被丢弃,根据RFC 2046, section 1:
MIME实现也必须忽略任何它们不认识的参数。
因此,如果
level
是一个已识别的参数(目前甚至{{link1:
text / html
mediatype}}都不是这种情况。是的,我知道它出现在多个示例中),正确的解决方案确实是这样的:
Accept: multipart/related
multipart/related
multipart/related
但是如果去掉level
参数,我们只剩下这个:
Accept: multipart/related
multipart/related
multipart/related
这在语义上与以下内容相同:
Accept: multipart/related
"Content-Type: : 多部分类型 MIME 提供了许多“多部分”类型。这些是将几个主体部分封装在一个消息中。在 HTTP 中,只有在客户端指示接受(使用 Accept:)多部分类型和每个组成主体部分的内容类型时,才可以返回多部分类型。 与 MIME 不同,主体部分(可能)包含 HTTP 元信息头字段,这些字段是重要的。" - Gunter Zeilinger