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

时间:2016-03-31 11:58:39

标签: http http-headers mime-types multipart http-accept-header

RFC 7231 - HTTP/1.1 Semantics and Content, 5.3 Content Negotiation未定义如何指定接受具有接受标头字段中正文部分的特定内容类型的多部分/相关内容类型。

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

FirefoxProfile firefoxProfile = new FirefoxProfile();    
firefoxProfile.setPreference("browser.privatebrowsing.autostart", true);

DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability(InternetExplorerDriver.FORCE_CREATE_PROCESS, true); 
capabilities.setCapability(InternetExplorerDriver.IE_SWITCHES, "-private");

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

DesiredCapabilities capabilities = DesiredCapabilities.operaBlink();
OperaOptions options = new OperaOptions();
options.addArguments("private");
capabilities.setCapability(OperaOptions.CAPABILITY, options);

Accept: multipart/related;type=text/html

什么是对的?既?

2 个答案:

答案 0 :(得分:5)

首先,HTTP是MIME- 之类的协议,而不是MIME- 兼容协议。引用RFC 7230, section 2.1

  

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

这一点非常重要,因为这会在处理MIME内容时给予我们一些自由。

Accept标题受RFC 7231, sec. 5.3.2约束。这里描述的语法允许列出逗号分隔的mediatypes(参见RFC 7230, sec. 7),除了HTTP特定的权重参数q之外,每个参数都包含任意数量的mediatype特定参数(参见{{3} }})。

RFC 7231, sec. 5.3.1讨论哪些媒体类型被认为对AcceptContent-Type标题有效:

  

HTTP使用Content-TypeAccept标头字段中的Internet媒体类型Section 3.1.1.1,以提供开放和可扩展的数据类型和类型协商。 [...]互联网媒体类型应根据[RFC2046]

中定义的程序在IANA注册

[BCP13]指的是[BCP13],最终导致RFC 6838

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

  

参数的存在与否可能对媒体类型的处理有重要影响,具体取决于媒体类型注册表中的定义。

multipart/related MIME类型本身受IANA Media Types Registry的约束。 RFC 2387明确要求type参数强制。它也是单个值,而不是列表。有趣的是,HTTP规范强调了boundary参数优先于Section 3.1的重要性。来自RFC 2046, section 5.1.1

  

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

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

Accept: multipart/related; type=text/html; boundary=--my-top-notch-boundary-

实际上,实施者似乎倾向于故意忽略这些要求,如RFC 7231, section 3.1.1.4所示。我通常不主张不遵守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

(注意:添加了行继续以提高易读性。请注意,行继续为this example,不应再在HTTP上下文中使用。)

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

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

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

所以,如果level是一个公认的参数(目前RFC 2046, section 1的情况就是如此。是的,我知道它出现在多个例子中),正确的解决方案确实是这个:

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

答案 1 :(得分:0)

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