CEL 匹配器语言参考文档

通用表达式语言 (CEL) 是一种开源的非图灵完备语言,可实现用于表达式求值的通用语义。服务扩展程序使用 CEL 条件的子集,根据属性数据做出链式评估决策。通常,条件表达式由一个或多个使用逻辑运算符(&&||!)联接的语句组成。

属性

对于任何给定的连接请求,代理都会提取属性,这些属性是一组上下文信息。属性具有固定的类型(例如 stringint),并且可能会根据上下文而存在或不存在。 在处理匹配条件期间,属性会公开给 CEL 运行时。 无法将属性发送到扩展服务。

请求属性

您可以从请求中提取以下属性:

属性 属性类型 说明
request.headers map{string,string} HTTP 请求标头的字符串到字符串映射。如果某个标头包含多个值,此映射中的值将是标头的所有值的英文逗号分隔字符串。此映射中的键均为小写。
request.method 字符串 HTTP 请求方法,例如 GETPOST
request.host 字符串 相当于 request.headers['host'] 的简便方法。
request.path 字符串 所请求的 HTTP 网址路径。
request.query 字符串

HTTP 网址查询,格式为 name1=value&name2=value2,显示在 HTTP 请求的第一行中。

未执行解码。

request.scheme 字符串 HTTP 网址 scheme,例如 HTTP 或 HTTPS。此属性的值均为小写。
request.backend_service_name 字符串

向其转发请求的后端服务。

不适用于边缘扩展服务。

request.backend_service_project_number 整数

使用共享 VPC 时,向其转发请求的后端服务的项目编号。

不适用于边缘扩展服务。

连接特性

您可以从连接中提取以下属性:

属性 属性类型 说明
source.ip 字符串 请求的源 IP 地址。
source.port 整数 下游客户端的连接端口。
connection.sni 字符串 下行 TLS 连接中所请求的服务器名称。
connection.tls_version 字符串 下行 TLS 连接的 TLS 版本。有效值:TLSv1TLSv1.1TLSv1.2TLSv1.3
connection.sha256_peer_certificate_digest 字符串 下行 TLS 连接中对等证书的十六进制编码 SHA256 哈希(如果存在)。

运算符

服务扩展程序支持多种运算符,您可以使用这些运算符通过简单的表达式语句构建复杂的匹配条件。Service Extensions 支持逻辑运算符(例如 &&||!)和字符串操作运算符(例如 x.contains('y'))。

字符串处理运算符用于匹配您定义的字符串或子字符串。例如,如果 HTTP 请求是向以 example.com 结尾的网域发出的,则 request.host.endsWith('.example.com') 的计算结果为 true

借助逻辑运算符,您可以在条件表达式中验证多个变量。例如,request.method == 'GET' && request.host.matches('.example.com') 连接了两个语句,并且要求这两个语句均为 true,才能生成总体结果 true

逻辑运算符

下表介绍了服务扩展程序支持的逻辑运算符。

示例表达式 说明
x == "foo" 如果 x 等于常量字符串字面量实参,则返回 true
x == R"fo'o" 如果 x 等于不解释转义序列的指定原始字符串字面量,则返回 true。原始字符串字面量便于表示代码必须使用转义序列字符的字符串。
x == y 如果 x 等于 y,则返回 true
x != y 如果 x 不等于 y,则返回 true
x && y 如果 xy 均为 true,则返回 true
x || y 如果 xy 或两者均为 true,则返回 true
!x 如果布尔值 xfalse,则返回 true;如果布尔值 xtrue,则返回 false
m['k'] 如果存在键 k,则返回字符串到字符串映射 m 中键 k 处的值。如果不存在键 k,则返回一个错误,导致正在评估的规则不匹配。

字符串操作运算符

下表介绍了服务扩展程序支持的字符串操作运算符。

表达式 说明
x.contains(y) 如果字符串 x 包含子字符串 y,则返回 true
x.startsWith(y) 如果字符串 x 以子字符串 y 开头,则返回 true
x.endsWith(y) 如果字符串 x 以子字符串 y 结尾,则返回 true
x.matches(y)

如果字符串 x 与指定的 RE2 模式 y 匹配,则返回 true

服务扩展程序在编译 RE2 模式时使用 RE2::Latin1 选项,该选项会停用 Unicode 功能。

边缘扩展功能允许您在每个 CEL 表达式中仅使用一个正则表达式。

x.lower() 返回字符串 x 的小写值。
x.upper() 返回字符串 x 的大写值。
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 的所有请求:

request.path.endsWith("/inventory") && request.headers["Hello"] != ""

限制

为服务扩展指定 CEL 表达式时,存在以下限制:

  • 每个扩展程序的表达式数量上限:边缘扩展程序为 1 个,其他扩展程序为 5 个
  • 每个正则表达式的字符数上限:100
  • 每个 CEL 表达式的字符数上限:500