我应该使用哪种字符编码作为HTTP头的编码?

156

我正在使用一个“有趣”的HTML特殊字符(✰)(请参见http://html5boilerplate.com/了解更多信息),用于 Server HTTP头,想知道是否符合规范。

  • 在Windows XP Pro SP 3上的Chrome开发工具中使用网络选项卡,我可以正常看到✰。

  • 在IE8中,✰没有正确呈现。

  • w3.org HTML验证器无法正确呈现它(显示“â °”)。

现在,我对字符编码并不太熟悉... 而且坦率地说,我并不太在乎它们; 我只是盲目地使用UTF-8,因为被告知要使用它。 :-)


这种差异是由不同解析器/浏览器/引擎/(它们称之为什么)中的错误引起的吗?

是否有关于HTTP头部“值”的允许字符的规范或列表?


38
这个问题更好地以一般方式提问:“在http头值中允许使用哪些字符”。 - Akrikos
2
现在,我对字符编码不是太热衷...坦白地说,我并不太关心它们;我只是盲目地使用UTF-8,因为别人告诉我要这么做。:-) - d4nyll
2个回答

152

简而言之:只有ASCII字符集是保证可用的。一些非ASCII字节是允许的,以实现向后兼容性,但是不应该被用于显示。

HTTPbis已经放弃了,并规定在标头中除ASCII外没有其他有用的编码:

历史上,HTTP允许带有ISO-8859-1字符集[ISO-8859-1]的文本字段内容, 仅通过使用[RFC2047]编码支持其他字符集。实际上,大多数HTTP标题字段值仅使用US-ASCII字符集[US-ASCII]的子集。新定义的标题字段应将其字段值限制为US-ASCII八位字节。接收方应将字段内容(obs-text)中的其他八位字节视为不透明数据。


此前,1999年的RFC2616定义为:

* TEXT的单词可以包含字符集ISO-8859-1 [22]以外的字符,仅当根据RFC2047 [14]的规则进行编码时才能包含。

RFC2047是MIME编码,因此它是:

=?UTF-8?Q?=E2=9C=B0?=

但我认为很少(如果有任何)客户端支持它。


7
那是什么意思?"✰"符号有效/被允许吗? - David Murdoch
10
稍微扩展一下非常有用的答案: "UTF-8" 是字符集,而 "Q" 表示该值将是“quoted-printable”格式。如果您要对该值进行BASE64编码,也可以使用“B”。 - GargantuChet
1
@porneL,那么“opaque data”是什么意思?当HTTP接收到这些“opaque data”时,接收方应该做什么 - Pacerier
1
@Pacerier "不透明数据" 意味着它是一个黑盒子,里面有一堆字节,应用程序不应该尝试显示或解释它(就像二进制数据)。它的处理取决于头文件,可能从“无操作”到“丢弃”不等。 - Kornel

10
请先阅读评论,本答案可能从正确的来源中得出错误的结论,需要编辑。

您可以使用任何可打印的ASCII字符,但不能使用特殊字符,例如✰(不是ASCII

提示:您可以在JSON中编码任何内容。

编辑:可能一开始不太明显,头部定义的字符编码仅适用于响应正文,而不适用于头部本身。(因为这会导致鸡生蛋蛋生鸡的问题。)


根据Penchant提供的spec,我希望能够总结所有相关定义。

message-header = field-name ":" [ field-value ]
field-name     = token
field-value    = *( field-content | LWS )

所以,我们需要的是 字段值
LWS            = [CRLF] 1*( SP | HT )
CRLF           = CR LF
CR             = <US-ASCII CR, carriage return (13)>
LF             = <US-ASCII LF, linefeed (10)>
SP             = <US-ASCII SP, space (32)>
HT             = <US-ASCII HT, horizontal-tab (9)>

LWS代表线性空白。实质上,LWS就是空格或制表符,但是您可以在空格或制表符之前开始新行,将字段值分成多行。

让我们简化一下:

field-value    = <any field-content or Space or Tab>

现在我们关注的是“field-content”。
field-content  = <the OCTETs making up the field-value
                 and consisting of either *TEXT or combinations
                 of token, separators, and quoted-string>
OCTET          = <any 8-bit sequence of data>
TEXT           = <any OCTET except CTLs,
                 but including LWS>
CTL            = <any US-ASCII control character
                 (octets 0 - 31) and DEL (127)>
token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@"
                 | "," | ";" | ":" | "\" | <">
                 | "/" | "[" | "]" | "?" | "="
                 | "{" | "}" | SP | HT

TEXT是最一般的,包括了其它所有内容-所以忘掉其它内容吧-。 这里是US-ASCII字符集(= ASCII)

正如你所看到的,所有可打印的ASCII字符都是被允许的。


5
你引用的段落与你所说的话是相矛盾的。为什么你说“没有像✰这样的特殊字符”?特殊字符只是“OCTET”,而且由于“TEXT”是除了“0-31”的任何“OCTET”,这意味着所有从“32”到“255”的“OCTET”都是被允许的。✰的“OCTET”是“226”、“156”和“176”,所有这三个“OCTET”都是被允许的,因此根据你引用的段落,“✰”是被允许的。 - Pacerier
2
@Pacerier,你似乎完全正确,我不明白为什么我得出了那样的结论。 - zupa
@Pacerier,我还没有准备好编辑它,因为我需要再次仔细检查规范。恐怕额外的细节限制在US-ASCII字符集上,这反过来会支持结论,但推理不足。 - zupa
4
说“你可以用JSON编码任何内容”是有点误导的。JSON允许使用Unicode字符,而HTTP标头应该是US-ASCII。Unicode字符将被视为“不透明”数据,因此其行为在HTTP规范中是未定义的。尽管如此,通过使用\uXXXX转义序列来转义Unicode字符,可以使JSON安全地包含在HTTP标头中。 - Jacob
@zupa,另一个问题是... "除了CTLs"是什么意思?这是否意味着允许使用字符CRLF?还是仅允许连续的序列"CR LF SP/HT"?(换句话说,标头值可以包含单个CRLFHT吗?标头值可以按任意顺序和数量包含字符CRLFHT吗?) - Pacerier

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