浏览器在发送请求时如何决定使用哪个字符集?我们应该如何处理?

4

tl;dr: 当浏览器/用户代理提交表单时,它以UTF-8格式提交(在我的测试中),但不包括此信息在HTTP请求中。用户代理如何决定使用UTF-8?应用程序代码(接收请求的代码)如何决定使用哪个字符集来解码传入的数据?


在过去的几天里,我一直在搜索互联网,以找出从浏览器发送到Web服务器时数据的编码方式。事实证明这是一个非常复杂的问题,因为在这个问题上没有明确的标准。

RFC2616(HTTP)基本上是基于ISO-8859-1和US-ASCII。但是存在扩展允许使用其他字符集(例如RFC2047)。 编辑: RFC2616已被RFC7231取代,后者已删除了有关ISO-8859-1的注释(请参见附录B)。

请求主体

基本上,当用户代理发送包含主体的请求时,问题似乎已经很好地定义了:使用包括charset参数的Content-Type头。例如:

Content-Type: text/plain; charset=utf-8

这在JavaScript中很容易实现。但今天,我遇到了一个问题,当使用HTML表单元素时,无法指定字符集。在搜索中,我遇到了这个SO问题,但我认为答案是错误的。它声称使用accept-charset属性。但从参考文献中可以看出,此标头用于告诉服务器客户端/用户代理可接受的字符集,而不是反过来。

相关的FORM属性enctype指定了提交文档的内容类型。但它只允许三个值,并且如果它们不按原样使用,则用户代理(在本例中为Chrome)默认为application/x-www-form-urlencoded。您无法指定字符集,这在我看来是好的,因为UA的工作是为您编码。

但是,到达服务器的请求完全没有关于所使用字符集的任何信息。那么应用程序代码应该如何决定使用哪种编码?

另一个问题是:用户代理如何决定在提交表单时使用哪种字符集?在我所有的测试中,它们都将其提交为UTF-8。但这从哪里来?嗅探网络流量并没有给我任何迹象。虽然,原始网页包含一个元标记,说明该页面使用UTF-8。就是这样吗?

假设UA正在使用与刚从服务器接收到的相同的字符集。但是,如果从应用程序A(以UTF-8格式)请求的页面包含具有针对应用程序B的POST操作的表单,则假设它可能不起作用(同源策略仅适用于XHRIO,对吧?)。在那种情况下,UA没有关于编码的“先验”信息。它如何决定选择哪种编码?

HTTP“序言”和标头

只是将其记录为参考

URI在2005年后得到了明确定义(请参见RFC3986),应使用UTF-8。在此之前,没有定义标准,这有点猜测。

标头值在RFC5987中得到了明确定义。


参考文献:

  • 超文本传输协议(HTTP)头字段参数的字符集和语言编码 - RFC5987
  • 在超文本传输协议(HTTP)中使用内容分发头字段附录C - RFC6266
  • HTML表单元素(enctype)
  • 统一资源标识符(URI):通用语法 - RFC3986

1
请不要再担心RFC2616了,它已经在几个月前被废弃了。在这种情况下,这与HTTP无关--正如答案中所指出的那样,这是HTML表单提交过程的一个属性。 - Julian Reschke
确实。我一直在查看“被淘汰的”参考文献,但不知何故错过了rfc7231,它在section 5.3.3中澄清了很多问题。经过一天的阅读RFC,我可能在某个时候走神了 :( - exhuma
1个回答

2
HTML5表单提交的用户代理选择编码的过程在4.10.22.5, 选择表单提交编码中描述。
如果表单上没有(有效的)accept-charset元素,则默认为UTF-8。
对于HTML 4,其默认值为:

[accept-charset] 属性的默认值是保留字符串 "UNKNOWN"。用户代理可以将此值解释为用于传输包含此FORM元素的文档的字符编码。


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