跳到主要内容

3. 请求行

请求行 (request-line) 以方法 token 开始, 后接一个空格 (SP), request-target, 另一个空格 (SP), 并以协议版本结束.

request-line   = method SP request-target SP HTTP-version

虽然 request-line 语法规则要求各组成元素之间用单个 SP 八位组分隔, 接收方 MAY 改为按空白分隔的词边界进行解析, 并且除 CRLF 终止符外, 将任何形式的空白视为 SP 分隔符, 同时忽略前导或尾随空白; 此类空白包括以下一个或多个八位组: SP, HTAB, VT (%x0B), FF (%x0C), 或裸 CR. 但是, 如果消息存在多个接收方且每个接收方对鲁棒性有自己独特的解释, 宽松解析可能导致请求走私安全漏洞 (参见 Section 11.2).

如 [HTTP] 的 Section 2.3 所述, HTTP 不对请求行长度设置预定义限制. 服务器收到比其实现的任何方法都更长的方法时, SHOULD 以 501 (Not Implemented) 状态码响应. 服务器收到比其愿意解析的任何 URI 都更长的 request-target 时, MUST 以 414 (URI Too Long) 状态码响应 (参见 [HTTP] 的 Section 15.5.15).

实践中可以见到各种临时性的请求行长度限制. RECOMMENDED 所有 HTTP 发送方和接收方至少支持 8000 个八位组的请求行长度.

3.1. 方法

方法 token 指示要在目标资源上执行的请求方法. 请求方法区分大小写.

method         = token

本规范定义的请求方法见 [HTTP] 的 Section 9, 其中还包含关于 HTTP 方法注册表以及定义新方法时的考虑事项.

3.2. 请求目标

request-target 标识要对其应用请求的目标资源. 客户端从其期望的目标 URI 派生出 request-target. request-target 有四种不同格式, 取决于所请求的方法以及该请求是否发往代理.

request-target = origin-form
/ absolute-form
/ authority-form
/ asterisk-form

request-target 中不允许出现空白. 遗憾的是, 一些用户代理未能正确编码或排除超文本引用中的空白, 导致这些不允许的字符作为格式错误请求行中的 request-target 被发送.

无效请求行的接收方 SHOULD 以 400 (Bad Request) 错误响应, 或者以 301 (Moved Permanently) 重定向并附带已正确编码的 request-target. 接收方 SHOULD NOT 尝试自动纠正并在不重定向的情况下处理该请求, 因为无效请求行可能是有意构造的, 用于绕过请求链上的安全过滤器.

客户端 MUST 在所有 HTTP/1.1 请求消息中发送 Host 头部字段 ([HTTP] 的 Section 7.2). 如果目标 URI 包含 authority 组成部分, 则客户端 MUST 为 Host 发送与该 authority 组成部分完全相同的字段值, 但排除任何 userinfo 子组成部分及其 "@" 分隔符 ([HTTP] 的 Section 4.2). 如果目标 URI 缺少 authority 组成部分或其未定义, 则客户端 MUST 发送字段值为空的 Host 头部字段.

对于任何缺少 Host 头部字段的 HTTP/1.1 请求消息, 以及任何包含多个 Host 头部字段行或 Host 头部字段值无效的请求消息, 服务器 MUST 以 400 (Bad Request) 状态码响应.

3.2.1. origin-form

request-target 最常见的形式是 "origin-form".

origin-form    = absolute-path [ "?" query ]

当直接向源服务器发起请求时, 除 CONNECT 或服务器范围的 OPTIONS 请求 (如下详述) 之外, 客户端 MUST 只将目标 URI 的绝对路径和查询组成部分作为 request-target 发送. 如果目标 URI 的路径组成部分为空, 客户端 MUST 在 request-target 的 origin-form 中发送 "/" 作为路径. 同时还会按 [HTTP] 的 Section 7.2 所定义发送 Host 头部字段.

例如, 若客户端希望直接从源服务器获取由以下 URI 标识的资源表示:

http://www.example.org/where?q=now

它会打开 (或复用) 到主机 "www.example.org" 的 80 端口的 TCP 连接, 并发送以下行:

GET /where?q=now HTTP/1.1
Host: www.example.org

随后发送请求消息的其余部分.

3.2.2. absolute-form

当向代理发起请求时, 除 CONNECT 或服务器范围的 OPTIONS 请求 (如下详述) 之外, 客户端 MUST 以 "absolute-form" 将目标 URI 作为 request-target 发送.

absolute-form  = absolute-URI

代理被请求尽可能从有效缓存中服务该请求, 或者代表客户端向下一个入站代理服务器或直接向 request-target 所指示的源服务器发出同样的请求. 此类消息 "forwarding" 的要求在 [HTTP] 的 Section 7.6 中定义.

请求行的 absolute-form 示例为:

GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1

即使 request-target 采用 absolute-form, 客户端也 MUST 在 HTTP/1.1 请求中发送 Host 头部字段, 因为这允许 Host 信息通过可能尚未实现 Host 的古老 HTTP/1.0 代理转发.

当代理收到 request-target 为 absolute-form 的请求时, 该代理 MUST 忽略收到的 Host 头部字段 (如有), 并改用 request-target 中的主机信息替换它. 转发此类请求的代理 MUST 基于收到的 request-target 生成新的 Host 字段值, 而不是转发收到的 Host 字段值.

当源服务器收到 request-target 为 absolute-form 的请求时, 源服务器 MUST 忽略收到的 Host 头部字段 (如有), 并改用 request-target 中的主机信息. 注意, 如果 request-target 没有 authority 组成部分, 在这种情况下将发送空的 Host 头部字段.

服务器 MUST 接受请求中的 absolute-form, 即使大多数 HTTP/1.1 客户端只会向代理发送 absolute-form.

3.2.3. authority-form

request-target 的 "authority-form" 仅用于 CONNECT 请求 ([HTTP] 的 Section 9.3.6). 它只包含隧道目的地的 uri-host 和端口号, 二者以冒号 (":") 分隔.

authority-form = uri-host ":" port

当发起 CONNECT 请求以通过一个或多个代理建立隧道时, 客户端 MUST 只将隧道目的地的主机和端口作为 request-target 发送. 客户端从目标 URI 的 authority 组成部分获取主机和端口, 但如果目标 URI 省略了端口, 则发送该 scheme 的默认端口. 例如, 发往 "http://www.example.com" 的 CONNECT 请求如下:

CONNECT www.example.com:80 HTTP/1.1
Host: www.example.com

3.2.4. asterisk-form

request-target 的 "asterisk-form" 仅用于服务器范围的 OPTIONS 请求 ([HTTP] 的 Section 9.3.7).

asterisk-form  = "*"

当客户端希望请求整个服务器的 OPTIONS, 而不是该服务器上某个具名资源的 OPTIONS 时, 客户端 MUST 只发送 "*" (%x2A) 作为 request-target. 例如:

OPTIONS * HTTP/1.1

如果代理收到 request-target 为 absolute-form 的 OPTIONS 请求, 且其中 URI 的路径为空并且没有查询组成部分, 则请求链上的最后一个代理在将请求转发给所指示的源服务器时, MUST 发送 "*" 作为 request-target.

例如, 请求:

OPTIONS http://www.example.org:8001 HTTP/1.1

会由最终代理在连接到主机 "www.example.org" 的 8001 端口之后转发为:

OPTIONS * HTTP/1.1
Host: www.example.org:8001

3.3. 重建目标 URI

当 request-target 采用 absolute-form 时, 目标 URI 就是 request-target. 在这种情况下, 服务器会将 URI 解析为其通用组成部分, 以供进一步评估.

否则, 服务器会根据连接上下文和请求消息的各个部分重建目标 URI, 以标识目标资源 ([HTTP] 的 Section 7.1):

  • 如果服务器配置提供了固定 URI scheme, 或受信任的出站网关提供了 scheme, 则该 scheme 用于目标 URI. 这在大规模部署中很常见, 因为网关服务器会接收客户端的连接上下文, 并将其替换为自己到入站服务器的连接. 否则, 如果请求通过安全连接接收, 则目标 URI 的 scheme 为 "https"; 如果不是, 则 scheme 为 "http".

  • 如果 request-target 采用 authority-form, 则目标 URI 的 authority 组成部分就是 request-target. 否则, 目标 URI 的 authority 组成部分是 Host 头部字段的字段值. 如果没有 Host 头部字段, 或其字段值为空或无效, 则目标 URI 的 authority 组成部分为空.

  • 如果 request-target 采用 authority-form 或 asterisk-form, 则目标 URI 的组合路径与查询组成部分为空. 否则, 目标 URI 的组合路径与查询组成部分就是 request-target.

  • 按上述方式确定重建后的目标 URI 各组成部分后, 可以通过串接 scheme, "://", authority, 以及组合路径与查询组成部分, 将它们重新组合为 absolute-URI 形式.