HTTP 请求
首先,我们看一下这个 HTTP 请求:
行数 内容
1 GET /serv/login.php?lang=en&profile=2 HTTP/1.1
2 Host: www.mydomain.com
3 User-agent: my small browser
4 Accept: image/jpeg, image/gif
5 Accept: image/png
请求行
第一行是请求行,它总是由三部分组成:
- METHOD:GET
- URI:/serv/login.php?lang=en&profile=2
- version tag:HTTP/1.1它们被一个叫 LWS(Linear White Spaces)的标准所分隔,也就是我们常见的空格,不过也可以由制表符或 CR/LF 加上空格/制表符所分隔。
这些方法本身无法包含“:”字符,它只能由字母组成。所有这些增加可描述性的表达形式都是 HAProxy 自行分割,避免了用户去编写复杂而可能不准确的正则表达式来匹配它们。
URI 可以有多种表达形式:
- 相对 URI:比如
/serv/login.php?lang=en&profile=2
是一个不含域名的完整 URL,它通常会被服务器、反向代理、透明代理接受。 - 绝对 URI:比如
http://192.168.0.12:8080/serv/login.php?lang=en&profile=2
,也称为 URL,它由一种“图式”组成:(协议名称后跟着://
)首先是一个域名或地址(有时会加上:
后跟着端口号),后面加上/
和一个相对 URI。通常一个代理会接受此类形式,支持 HTTP/1.1 的服务器也会接受这种形式。 - 一个星号(“
*
”):此形式是不可靠的,仅在和OPTIONS
方法联合使用时才会被接受,用于适配查询下一跳。 - 地址加端口号:比如
192.168.0.1:8080
,用于CONNECT
方法来和一个 HTTP 代理建立 TCP 隧道,通常用于 HTTPS 协议,但也可能是其他协议。在一个相对 URI 中,有两个部分是被确定好的:?
前面的部分称为路径(path),通常是服务器上某个静态对象的相对路径;?
后面的部分称为查询字符串(query string),大多用来发送GET
请求给动态脚本或指定语言、框架、应用程序等。
请求头
从第二行开始就是请求头。它由键名
+ :
+ 值
组成。传统上,冒号的后面会加上一个 LWS,不过并没有强制要求。
如果请求头有多个键名相同的值,它们可能会被合并到一行,然后用逗号,
分隔开多个值,在Cookie:
这个键就常见这种情况。如果一个请求头的开头是一个 LWS,那么它可能会跨越多行,本文上面例子的第 4、5 行Accept:
就定义了三个值。
与我们通常认知相反的是,请求头的键和值对大小写并不敏感。
请求头中的第一个空行标记头部的结束。很多人认为末尾会有两个 LF,但这种说法不是很准确,尽管两个 LF 确实代表一个合法的空行。
幸运的是,HAProxy 对组合复杂的请求头作了细致的检查、计算和分析,所以我们不用担心请求头会被写成什么样子。但如果一个应用因为用了不寻常的东西而充满 Bug,那指责他也无可厚非。
请注意:
基于 RFC7231 的建议,HAProxy 用 LWS 替换请求头中的换行符来连接多行请求头,这对纠正分析结果、优化 HTTP 解析器效率、简化复杂结构颇有帮助。