执行顺序
本文说明 OpenResty Edge 处理 HTTP 或 HTTPS 请求时,全局改写规则、页面规则和页面规则动作的执行顺序,以及多条规则或多项设置同时影响同一内容时的优先级。
你可以用它判断功能之间的关系。例如,WAF 是否会检查页面规则改写后的 URI,响应头动作是否会作用于缓存命中的响应。
本文适用于 OpenResty Edge 26.9.1-1 及之后的版本,仅涵盖 HTTP 和 HTTPS 应用。
版本标注
引入版本列表示包含该项的第一个 OpenResty Edge 版本:
- 单元格为空,表示该项在 OpenResty Edge
22.12.1-1之前已经提供。 24.9.1-1这样的版本号,表示包含该项的第一个版本。- 即将发布表示该项还没有包含在已发布的版本中。
总览
节点找到请求所属的应用后,请求会依次经过以下阶段:
- 全局改写规则:对分区内的每个应用执行全局改写规则。
- 应用规则:执行应用的自定义 Edge 语言规则和页面规则。
- 转发前处理:应用最终的 URI,启用错误页,确定缓存和上游,然后执行 WAF。
- 缓存与上游:查找缓存;未命中缓存时,将请求转发到上游。
- 响应头:执行响应头动作。
- 响应体:执行响应体动作和压缩。
- 日志:写入日志并发送事件。
某些动作会在进入“缓存与上游”阶段前结束请求,例如退出当前请求并返回状态码、限速拒绝和 WAF 拦截。此时节点会跳过后续请求处理,直接生成响应;该响应仍会经过响应头、响应体和日志阶段。不同动作的差异见在 WAF 之前拒绝的请求和在 WAF 之前发送的响应。
规则顺序
规则匹配后,按以下顺序处理:
- 按从上到下的顺序执行动作列表。全局自定义动作在列表中的位置决定其执行顺序。
- WAF:登记一次 WAF 检查。实际检查在“转发前处理”阶段统一执行。
- 内容:发送配置的内容,并停止执行后续页面规则。见在 WAF 之前发送的响应。
- 代理:记录上游配置;节点会在“转发前处理”阶段确定实际使用的上游。
- 缓存:记录缓存配置;节点会在“转发前处理”阶段应用这些配置。
- 当此规则匹配时,跳过所有后续页面规则:停止执行后续页面规则。
动作的生效时间
- 规则执行时:规则匹配后立即执行,后续规则可以看到执行结果。
- 转发前处理阶段或响应头阶段:动作先记录配置,再由节点在对应阶段应用。
结束请求列说明动作是否会在当前规则中结束请求。总是表示必定结束请求;写有条件时,只有满足该条件才会结束请求。空白表示该动作不会结束请求。
| 动作 | 生效时间 | 结束请求 | 引入版本 |
|---|---|---|---|
| 设置 URI | 规则执行时 | ||
| 添加 URI 前缀 | 规则执行时 | ||
| 删除 URI 前缀 | 规则执行时 | ||
| 删除 URI 片段 | 规则执行时 | ||
| 设置 URI 参数 | 规则执行时 | ||
| 追加 URI 参数 | 规则执行时 | ||
| 删除 URI 参数 | 规则执行时 | ||
| 设置请求头 | 规则执行时 | ||
| 添加请求头 | 规则执行时 | ||
| 删除请求头 | 规则执行时 | ||
| 设置变量 | 规则执行时 | ||
| 记录错误消息 | 规则执行时 | ||
| 延迟 | 规则执行时 | ||
| 使用 Edge 语言 | 规则执行时 | ||
| 运行 Lua 模块 | 规则执行时 | ||
| 镜像请求 | 规则执行时 | ||
| 记录 WAF 日志 | 规则执行时 | 23.3.1-1 | |
| 设置上传的文件参数 | 规则执行时 | 23.3.1-1 | |
| 启用 S3 认证 | 规则执行时 | 25.9.1-1 | |
| 限制请求速率 | 规则执行时 | 拒绝请求时 | |
| 限制请求数 | 规则执行时 | 拒绝请求时 | |
| 限制请求并发量 | 规则执行时 | 拒绝请求时 | 24.9.2-1 |
| 封锁请求 | 规则执行时 | 拒绝请求时 | |
| 封禁 IP 地址列表 | 规则执行时 | 客户端 IP 在列表中时 | 26.3.2-1 |
| 启用 Basic 认证 | 规则执行时 | 认证失败时 | |
| 启用 OpenIDC 认证 | 规则执行时 | 把客户端重定向到身份提供方时 | |
| OAuth2 JWT 验证 | 规则执行时 | 验证失败时 | |
| OAuth2 introspection 验证 | 规则执行时 | 验证失败时 | |
| 启用 hCaptcha | 规则执行时 | 客户端尚未通过验证时 | |
| 启用 OpenResty Edge 内置 Captcha | 规则执行时 | 客户端尚未通过验证时 | |
| 启用私有访问 Token | 规则执行时 | 客户端尚未通过验证时 | 26.9.1-1 |
| 启用熔断器 | 规则执行时 | 熔断器处于打开状态时 | |
| 启用 CSRF token | 规则执行时 | token 检查失败时 | 23.3.1-1 |
| 启用 SSL 客户端验证 | 规则执行时 | 客户端证书验证失败时 | |
| 封禁 IP 地址 | 规则执行时 | 总是 | 26.3.2-1 |
| 退出当前请求并返回状态码 | 规则执行时 | 总是 | |
| 重定向 | 规则执行时 | 总是 | |
| 关闭连接 | 规则执行时 | 总是 | 24.9.1-1 |
| 输出响应体 | 规则执行时 | 总是 | |
| 返回静态文件 | 规则执行时 | 总是 | |
| 最大请求体大小 | 转发前处理阶段 | ||
| 设置代理 URI | 转发前处理阶段 | ||
| 重写代理 URI 前缀 | 转发前处理阶段 | ||
| 设置代理主机 | 转发前处理阶段 | ||
| 定制错误页 | 转发前处理阶段 | ||
| 设置代理头 | 缓存与上游阶段 | ||
| 追加代理头值 | 缓存与上游阶段 | ||
| 传递请求头 | 缓存与上游阶段 | 25.12.1-1 | |
| 传递请求体 | 缓存与上游阶段 | 25.12.1-1 | |
| 使用下游服务器地址作为上游源地址 | 缓存与上游阶段 | 22.12.1-1 | |
| 启用 WebSocket | 缓存与上游阶段 | ||
| 启用代理缓存重新验证 | 缓存与上游阶段 | ||
| 使用旧代理缓存 | 缓存与上游阶段 | ||
| 绕过代理缓存 | 缓存与上游阶段 | 26.6.14-1 | |
| 禁用代理缓存 | 缓存与上游阶段 | 26.6.14-1 | |
| 禁用请求缓冲 | 缓存与上游阶段 | ||
| 禁用代理响应缓冲 | 缓存与上游阶段 | 23.12.1-1 | |
| 拦截上游错误 | 缓存与上游阶段 | ||
| 启用 HTTP 重定向跟随 | 缓存与上游阶段 | 26.9.2-1 | |
| 启用 HTTP 分片 | 缓存与上游阶段 | 即将发布 | |
| 设置响应头 | 响应头阶段 | ||
| 添加响应头 | 响应头阶段 | ||
| 删除响应头 | 响应头阶段 | ||
| 设置响应 Cookie | 响应头阶段 | ||
| 设置响应 Cookie 的 SameSite | 响应头阶段 | 23.3.1-1 | |
| 设置缓存过期时间 | 响应头阶段 | ||
| 根据后缀名设置响应内容类型 | 响应头阶段 | ||
| 响应体过滤 | 响应体阶段 | 23.3.1-1 | |
| 捕获响应体 | 响应体阶段 | ||
| 启用网关 Gzip | 响应体阶段 | ||
| 启用网关 Brotli | 响应体阶段 | ||
| 启用网关 Zstandard | 响应体阶段 | 25.6.1-1 | |
| 设置 Gzip 类型 | 响应体阶段 | ||
| 设置 Brotli 类型 | 响应体阶段 | ||
| 设置 Zstandard 类型 | 响应体阶段 | 25.6.1-1 | |
| 限制响应数据速率 | 响应体阶段 | ||
| 启用 OpenTelemetry 跟踪 | 日志阶段 | 24.9.2-1 | |
| 设置 OpenTelemetry Span 名 | 日志阶段 | 24.9.2-1 | |
| 启用限流事件 | 日志阶段 | ||
| 启用熔断器事件 | 日志阶段 | ||
| 禁用访问日志 | 日志阶段 |
设置 URI及其他 URI 动作会立即影响后续规则看到的 URI。节点会在“转发前处理”阶段把最终 URI 应用到请求。
启用 CSRF token会在规则执行时检查 token,并在响应体阶段注入 token。
镜像请求会在规则执行时发送请求副本,并等待副本请求完成。启用异步请求镜像后,节点会在“缓存与上游”阶段发送副本,不等待其完成;如果请求提前结束,则不会发送副本。
OpenTelemetry 相关动作会将请求标记为需要跟踪。请求结束时,节点会导出 span。
限速动作和封锁请求的以下拒绝方式在 22.12.1-1 之后加入:
- JavaScript 挑战验证和重定向验证(
23.3.1-1) - 返回页面模版(
24.3.1-1) - 标记为拒绝(
24.9.7-1) - 封禁 IP 地址(
26.3.2-1) - 私有访问 Token(
26.9.1-1) - 无延迟选项在
24.9.1-1中加入。 - 延迟日志在
26.9.20-1中加入。 - 即将发布:仅记录日志只在日志阶段把请求写入 CC 日志,不会延迟或拒绝请求。
在 WAF 之前拒绝的请求
以下情况下,请求在规则执行时直接结束,跳过转发前处理阶段:
- 限速动作或封锁请求拒绝了请求。
- 执行了封禁 IP 地址,或封禁 IP 地址列表匹配到客户端。节点关闭连接,不写访问日志。
- 启用 Basic 认证、OAuth2 JWT 验证或 OAuth2 introspection 验证失败。
- 启用 hCaptcha、启用 OpenResty Edge 内置 Captcha 或启用私有访问 Token 向尚未通过验证的客户端发出挑战。
- 启用 OpenIDC 认证把客户端重定向到身份提供方。
- 启用熔断器动作发现熔断器处于打开状态。
在 WAF 之前发送的响应
输出响应体、返回静态文件和内容区域会在 WAF 执行之前发送响应。
冲突与共用项的优先级
规则之间
下表中的“第一”和“最后”均指实际执行顺序:先执行全局改写规则,再执行页面规则。页面规则依次为置顶规则、普通规则和置底规则;每组内均从上到下执行。
同一条规则内,先执行动作列表,再依次处理 WAF、内容、代理和缓存区域。后执行的设置会覆盖先执行的设置。
| 项目 | 以哪一项为准 |
|---|---|
| 代理区域中的代理到上游 | 最后执行的匹配规则 |
| 缓存 key 组合以及缓存区域的其他选项 | 最后执行的匹配规则。默认启用缓存见下面两行。 |
| 状态码 200 的默认启用缓存 | 最后执行的匹配规则 |
| 其他状态码的默认启用缓存 | 当前版本以第一条匹配的规则为准。即将发布的版本改为以最后执行的匹配规则为准,与状态码 200 一致。 |
| 设置代理 URI 和重写代理 URI 前缀 | 最后执行的动作 |
| 设置代理主机 | 最后执行的动作 |
| 最大请求体大小 | 最后执行的动作 |
| 同一状态码的定制错误页 | 最后执行的动作 |
| 设置缓存过期时间和浏览器缓存 | 后执行的一项。在同一条规则中,浏览器缓存在动作列表之后执行,以它为准。 |
| 同名的设置请求头、设置代理头或设置 URI 参数 | 最后执行的动作。添加请求头和追加 URI 参数则会再添加一个值。 |
| 同一个头的设置请求头和设置代理头 | 上游收到的是设置代理头的值。后续规则的条件和 WAF 看到的是设置请求头的值。 |
| 同名的设置响应头、添加响应头和删除响应头 | 按执行顺序依次生效。设置响应头还会替换上游返回的同名响应头。 |
设置缓存过期时间或浏览器缓存,与作用于 Cache-Control 或 Expires 的响应头动作 | 以设置缓存过期时间或浏览器缓存为准,节点在响应头动作之后应用它们 |
| 多条规则的 WAF 区域 | 按规则顺序执行每一次已登记的检查。某一次检查拦截了请求后,请求结束。 |
| 多条规则中的限速动作和封锁请求 | 每个匹配的动作都在所在规则执行并各自计数。第一个拒绝请求的动作结束请求。 |
页面规则与设置之间
有些项目也可以在应用的设置和全局配置 > 通用中设置。对于页面规则匹配的请求,以页面规则的动作为准。应用的设置优先于全局配置,除非它被设为使用全局配置。
| 项目 | 优先级,从高到低 |
|---|---|
| 请求体大小上限 | 最大请求体大小动作、应用设置中的应用自定义的最大请求体大小、全局配置中的最大请求体大小 |
| Gzip | 启用网关 Gzip 和设置 Gzip 类型动作、应用设置中的使用 Gzip 压缩响应内容、全局配置中的 Gzip |
| Brotli | 启用网关 Brotli 和设置 Brotli 类型动作、应用设置中的使用 Brotli 压缩响应内容、全局配置中的 Brotli |
| Zstandard | 启用网关 Zstandard 和设置 Zstandard 类型动作、应用设置中的使用 Zstandard 压缩响应内容、全局配置中的 Zstandard |
| 缓存重新验证 | 启用代理缓存重新验证动作、应用设置中的代理缓存重新验证、全局配置中的代理缓存重新验证 |
| 旧缓存 | 使用旧代理缓存动作、应用设置中的应用自定义的旧代理缓存、全局配置中的使用旧代理缓存 |
| 拦截上游错误 | 拦截上游错误动作、全局配置中的拦截源站错误页。启用 HTTP 重定向跟随也会开启拦截。 |
| 状态码的错误页 | 定制错误页动作、全局配置中的启用 OpenResty Edge 错误页 |
应用的设置在全局改写规则之后生效。因此,没有设为使用全局配置的应用设置会覆盖全局改写规则中的同类动作。应用设置或全局配置中的请求体大小上限,也会覆盖全局改写规则中的最大请求体大小动作。
WAF
页面规则匹配后,WAF区域会登记一次 WAF 检查。节点会在“转发前处理”阶段统一执行所有已登记的检查,执行时间位于全部页面规则和页面底部自定义 Edge 语言规则之后。WAF 的配置方法见开启应用的 WAF。
因此:
- WAF 检查的是页面规则处理之后的请求,包括改写后的 URI、修改后的请求头和请求体。
- 无论规则排在前面还是后面,其动作都会先于 WAF 执行。限速、验证码和认证检查可能在 WAF 执行前结束请求;退出当前请求并返回状态码等动作则会在请求结束前先执行 WAF。
- 输出响应体、返回静态文件和内容区域会在 WAF 执行前发送响应。
- WAF 白名单的条件在页面规则执行之前检查,检查对象是原始请求。匹配的条目作用于每一次 WAF 检查。
- WAF 在查找缓存之前执行,因此由缓存响应的请求同样会被检查。
- WAF 当前只支持检查请求,暂不支持检查响应。拦截动作为仅记录日志时,捕获响应体(
23.6.1-1)会把部分响应体写入 WAF 日志。 - 被拦截的请求仍然经过响应头、响应体和日志阶段,因此响应头动作和日志同样作用于拦截响应。
以下 WAF 选项在 22.12.1-1 之后加入:拦截动作关闭连接、重定向验证和 JavaScript 挑战验证(23.3.1-1),偏执级别(26.6.1-1),以及拦截动作私有访问 Token 和自定义动作(26.9.1-1)。