通用表达式语言 (CEL) 是一种开源的非图灵完备语言,可实现表达式求值的通用语义。Service Extensions 使用 CEL 条件的子集,根据特性数据做出链评估决策。通常,条件表达式由一个或多个使用逻辑运算符(&&、|| 或 !)联接的语句组成。
属性
对于任何给定的连接请求,代理都会提取属性,这些属性是一组上下文信息。属性具有固定类型(例如 string 或 int),并且可能存在或不存在,具体取决于上下文。在匹配条件处理期间,属性会向 CEL 运行时公开。如需将特定属性转发到扩展服务或插件,请使用 forwardAttributes 字段。如需了解详情,请参阅支持的属性。
请求属性
您可以从请求中提取以下属性:
| 属性 | 类型 | LbEdge |
LbRoute |
LbTraffic |
Authz |
CdnEdge |
说明 |
|---|---|---|---|---|---|---|---|
request.headers |
地图 | ✓ | ✓ | ✓ | ✓ | ✓ | HTTP 请求标头的字符串到字符串映射,其中所有键均为小写。 |
request.method |
字符串 | ✓ | ✓ | ✓ | ✓ | ✓ | HTTP 请求方法(例如 GET、POST)。 |
request.host |
字符串 | ✓ | ✓ | ✓ | ✓ | ✓ | 等同于 request.headers['host']。 |
request.path |
字符串 | ✓ | ✓ | ✓ | ✓ | ✓ | 所请求的 HTTP 网址路径。 |
request.query |
字符串 | ✓ | ✓ | ✓ | ✓ | ✓ | 网址查询字符串 (name1=value&name2=value2)。 |
request.scheme |
字符串 | ✓ | ✓ | ✓ | ✓ | ✓ | 网址协议(http 或 https)。 |
request.backend_service_name |
字符串 | — | ✓ | ✓ | — | — | 后端服务名称。 |
request.backend_service_project_number |
整数 | — | ✓ | ✓ | — | — | 后端服务项目编号。 |
连接特性
您可以从连接中提取以下属性:
| 属性 | 类型 | LbEdge |
LbRoute |
LbTraffic |
Authz |
CdnEdge |
说明 |
|---|---|---|---|---|---|---|---|
source.ip |
字符串 | ✓ | ✓ | ✓ | ✓ | — | 客户端 IP 地址。 |
source.port |
整数 | ✓ | ✓ | ✓ | ✓ | ✓ | 客户端连接端口号。 |
source.client_region |
字符串 | ✓ | — | ✓ | — | ✓ | 由两个字母组成的客户端国家/区域代码。 |
connection.sni |
字符串 | ✓ | — | ✓ | ✓ | ✓ | 下游 TLS 服务器名称指示。 |
connection.tls_version |
字符串 | ✓ | — | ✓ | ✓ | ✓ | 下行 TLS 版本(例如 TLSv1.2、TLSv1.3)。 |
connection.sha256_peer_certificate_digest |
字符串 | ✓ | — | ✓ | ✓ | — | 对等证书 SHA-256 摘要。 |
运算符
Service Extensions 支持多种运算符,您可以使用这些运算符通过简单的表达式语句构建复杂的匹配条件。Service Extensions 支持逻辑运算符(例如 &&、|| 和 !)以及字符串操作运算符(例如 x.contains('y'))。
字符串操作运算符会匹配您定义的字符串或子字符串。例如,如果向以 example.com 结尾的网域发出 HTTP 请求,则 request.host.endsWith('.example.com') 的求值结果为 true。
逻辑运算符可让您在条件表达式中验证多个变量。例如,request.method == 'GET' && request.host.matches('.example.com') 连接了两个语句,并且要求这两个语句都为 true,才能生成总体结果 true。
逻辑运算符
下表介绍了 Service Extensions 支持的逻辑运算符。
| 示例表达式 | 说明 |
|---|---|
x == "foo" |
如果 x 等于常量字符串字面量实参,则返回 true。 |
x == R"fo'o" |
如果 x 等于不解释转义序列的指定原始字符串字面量,则返回 true。原始字符串字面量便于表示代码必须使用转义序列字符的字符串。 |
x == y |
如果 x 等于 y,则返回 true。 |
x != y |
如果 x 不等于 y,则返回 true。 |
x && y |
如果 x 和 y 均为 true,则返回 true。 |
x || y |
如果 x、y 或两者均为 true,则返回 true。 |
!x |
如果布尔值 x 为 false,则返回 true;如果布尔值 x 为 true,则返回 false。 |
m['k'] |
如果键 k 存在,则返回字符串到字符串映射 m 中的键 k 处的值。如果键 k 不存在,则返回一个错误,导致正在评估的规则不匹配。 |
k in m |
如果键 k 存在于字符串键控映射 m 中,则返回 true。否则,返回 false。 |
字符串操作运算符
下表介绍了 Service Extensions 支持的字符串操作运算符。
| 表达式 | 说明 |
|---|---|
x.contains(y) |
如果字符串 x 包含子字符串 y,则返回 true。 |
x.startsWith(y) |
如果字符串 x 以子字符串 y 开头,则返回 true。 |
x.endsWith(y) |
如果字符串 x 以子字符串 y 结尾,则返回 true。 |
x.matches(y) |
如果字符串 Service Extensions 在编译 RE2 模式时会使用 RE2::Latin1 选项,该选项会停用 Unicode 功能。 Edge 扩展程序仅允许每个 CEL 表达式使用一个正则表达式。 |
int(x) |
将字符串结果 x 转换为 int 类型。您可以使用标准算术运算符(例如大于 [>] 和小于或等于 [≤])将转换后的字符串用于整数比较。这仅适用于可以为整数的值。 |
示例表达式
匹配发送给主机 example.com 并将 123 中的后端服务 bs1 作为最终目的地的所有请求:
request.host == "example.com" && request.backend_service_name == "bs1" && request.backend_service_project_number == 123
匹配路径为 */inventory 且包含 HTTP 标头 Hello 的所有请求。请注意,对于 CEL 匹配,标头名称不区分大小写:
request.path.endsWith("/inventory") && "Hello" in request.headers
限制
为 Service Extensions 指定 CEL 表达式时,存在以下限制:
- 每个扩展程序的表达式数量上限:边缘扩展程序为 1,其他扩展程序为 5
- 每个正则表达式的字符数上限:100
- 每个 CEL 表达式的字符数上限:500