HTTP标头值允许哪些字符?

时间:2017-12-07 03:59:56

标签: http http-headers

在研究HTTP/1.1 standard之后,特别是第31页和相关的我得出结论,任何8位八位字节都可以出现在HTTP标头值中。即代码为[0,255]范围的任何字符。

然而我试过的HTTP服务器拒绝接受代码> 127(或大多数US-ASCII不可打印的字符)。

以下是标准中使用的语法摘录:

message-header = field-name ":" [ field-value ]
field-name     = token
field-value    = *( field-content | LWS )
field-content  = <the OCTETs making up the field-value and consisting of
                  either *TEXT or combinations of token, separators, and
                  quoted-string>

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)>
CRLF           = CR LF
LWS            = [CRLF] 1*( SP | HT )
OCTET          = <any 8-bit sequence of data>
CHAR           = <any US-ASCII character (octets 0 - 127)>
CTL            = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
TEXT           = <any OCTET except CTLs, but including LWS>

token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\"
               | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT

quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext         = <any TEXT except <">>
quoted-pair    = "\" CHAR

正如您所看到的,field-content可以是quoted-string,这是一个引用的TEXT序列(即除"之外的任何8位八位字节和来自的值{ [0-8, 11-12, 14-31, 127]范围)或quoted-pair\后跟[0, 127]范围内的任何值)。即任何8位字符序列都可以通过引用它并使用\)为特殊符号添加前缀来传递。

(请注意,标准不会以任何特殊方式处理NUL(0x00)个字符)

但是,显然我所尝试的所有服务器都不符合标准或自1999年以来标准发生了变化,或者我无法正确阅读。

那么...... HTTP标头值中允许哪些字符以及为什么?

P.S。所有这些背后的原因:我正在寻找一种在HTTP标头值中传递utf-8编码序列的方法(如果可能的话,不需要额外的编码)。

2 个答案:

答案 0 :(得分:5)

RFC 2616已过时(请参阅https://www.rfc-editor.org/info/rfc2616),相关部分已被RFC 7230取代(请参阅https://www.greenbytes.de/tech/webdav/rfc7230.html#rfc.section.A.2.p.9):

  

评论和引用字符串文本中不再允许使用NUL八位字节,   并澄清了处理反斜杠的问题。该   引用对规则不再允许转义其他控制字符   比HTAB。 标题字段中的非US-ASCII内容和原因短语   已被废弃并变得不透明(删除了TEXT规则)。   (第3.2.6节)

从本质上讲,RFC 2616默认为ISO-8859-1,无论如何这都是不够的,也不是可互操作的。因此,RFC 7230已弃用字段值中的非ASCII八位字节。建议在其上使用转义机制(例如RFC 8187中定义的,或普通URI-percent-encoding)。

答案 1 :(得分:-1)

看起来好像HTTP/1.1 specs中有错误。正如您所指出的,§4.2将字段内容描述为OCTET:

  

field-content =构成字段值的OCTET

OCTET在§2.2中定义为:

  

OCTET =任何8位数据序列

这些行是你的结论的基础,八位字节&gt;应该允许127,当然我知道你是如何得出这个结论的。在§4.2中提到OCTET是误导性错误;它应该是CHAR。

如果您从头开始阅读§4.2(消息标题),您将注意到以下指导:

  

HTTP标头字段...遵循与RFC 822的第3.1节中给出的相同的通用格式

如果我们按照指示行事并转到RFC 822,特别是§3.1.2(标题字段的结构),我们将学习以下内容:

  

字段名称必须由可打印的ASCII字符组成   (即值在33.到126之间的字符。   十进制,冒号除外)。 田野体可以由任何体构成   ASCII字符,CR或LF除外。

因此,虽然HTTP / 1.1是在1999年编写的,但他们使用1982年的定义来描述字段内容。在1982年,字符0-127被称为“ASCII”,128-255被称为“扩展ASCII”。现在,在这个答案中,我不打算参与使用术语“扩展ASCII”时引起的the food fight我将简单地指向RFC 822的§3.3,以定义然后被视为“任何ASCII字符”的内容

  

CHAR =任何ASCII字符(八进制:0-177,十进制:0.-127。)

所以你有它 - 吸烟枪。 “ASCII”在1982年停止在127. RFC2616§4.2的书面段落部分指出了你正确的方向,不幸的是后来在同一部分滥用令牌OCTET导致你失去了这个兔子洞。