在研究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编码序列的方法(如果可能的话,不需要额外的编码)。
答案 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导致你失去了这个兔子洞。