本文讲述API网关的参数以及条件表达式的使用。
1. 概述
在插件中,支持用户从当前的请求、应答或系统上下文中获取参数,并使用自定义的条件表达式对参数进行判断,本文描述参数的定义方法与条件表达式的书写方法。
2. 参数的定义
2.1. 定义方式
在使用条件表达式前,需要先在parameters字段中将所有需要在条件表达式中需要使用的参数进行显式定义,参考下面的例子:
---
parameters:
method: "Method"
appId: "System:CaAppId"
action: "Query:action"
userId: "Token:UserId"parameters字段类型是字符串类型的键值对,key和value的定义规范为:
key表示在条件表达式中使用的变量名,变量名的规则为[a-zA-Z_][a-zA-Z0-9]+,唯一。value表示参数所在的位置,使用{location}或{location}:{name}的方式进行定义,请参考如下的例子:location表示参数所在的位置,参考下一节的详细描述。name表示参数的名称,用于在所在位置中定位参数,比如Query:q1表示请求的QueryString中名字为q1的第一个值。
2.1. 参数的支持位置
在使用条件表达式前,我们需要先定义参与条件表达式计算的参数,目前API网关支持在插件中直接使用如下位置的参数
位置名称 | 适用范围 | 说明 |
Method | 请求 | HTTP请求方法(大写),如:
… |
Path | 请求 | HTTP完整请求路径,如:
|
StatusCode | 应答 | 后端的HTTP应答码,如:
|
ErrorCode | 应答 | |
Header | 请求/应答 | 使用
|
Query | 请求 | 使用 |
Form | 请求 | 使用 |
Host | 请求 | 使用 |
Parameter | 请求 | 使用 |
BodyJsonField | 应答* | 使用 |
System | 请求/应答 | 使用 |
Token | 请求/应答 | 当处于jwt插件认证时,使用 |
XFF | 请求 | 填写格式为 |
取值规则的说明
参数访问控制插件,流量控制插件,后端路由插件发生在请求阶段,插件仅支持适用范围为请求的参数位置:
Method、Path、Header、Query、Form、Parameter、System、Token、XFF。错误码映射插件发生在应答阶段,插件仅支持适用范围为应答的参数位置:
StatusCode、ErrorCode、Header、BodyJsonField、System、Token。Method、Path、StatusCode、ErrorCode和XFF这几个位置仅提供Location即可,不需要Name。Header位置的参数,当用于请求阶段的插件时,读取来自客户端请求中的Header。当用于应答阶段的插件时,读取来自后端应答中的Header 。Parameter位置的参数,仅用于请求阶段的插件,查找API定义中同名的参数,使用参数名而非后端参数名查找,当参数不存在时返回为null。Host位置的参数,仅支持在泛域名参数提取,参考使用自定义域名调用API, 完整的Host请使用System:CaDomain读取系统参数。Path返回为完整的请求路径,如果需要Path位置的参数,请使用Parameter位置的参数。BodyJsonField位置的参数,目前仅支持在错误码映射插件中使用,使用JSONPath方式读取应答JSON包体的值,参考JSONPath使用说明。Token当配置了JWT认证插件时,使用Token:{CliamName}可以读取在插件定义的值,参考对应插件的文档。
2.3. JSONPath使用说明
用于BodyJsonField位置,目前仅用于错误码映射插件,用于从后端返回的json包体中提取json中的字段,关于JSONPath的详细规范说明,请参考JSONPath介绍文档。
例子:使用
code:"BodyJsonField:$.result_code"可以从如下的包体中得到result_code的值,对于如下的包体,可以解析到code:ok。
{ "result_code": "ok", "message": ... }2.4. 系统参数列表
参数名称 | 参数含义 | 取值列表 |
CaClientIp | 请求来源客户端IP。 | 如: |
CaDomain | 请求的完整域名(Host头)。 | 如:
|
CaAppId | 请求的 APP 的 ID。 | 如:
|
CaAppKey* | 请求的 APP 的 Key。 | 如:
|
CaRequestId | 网关生成的唯一请求ID。 | 如:
|
CaApiName | API 名称。 | 如:
|
CaHttpSchema | 调用协议。 | 取值范围: |
CaClientUa | 客户端的UserAgent头。 | 透传客户端上传的值 |
CaCloudMarketInstanceId | 云市场购买关系ID。 | 云市场 |
CaMarketExpriencePlan | 是否开通云市场体验计划。 | 开通: 未开通: |
3. 条件表达式
条件表达式可在插件或其他场景中使用,用于在需要的场景中执行灵活的条件判断。
3.1. 基本语法
条件表达式与SQL表达式类似,比如:
$A > 100 and '$B = 'B'。表达式的基本为
{参数} {操作符} {参数}格式,如:$A > 100参数支持变量参数或常量参数。变量参数以$开头,用于引用在上下文中定义好的参数,例如:parameters中定义了q1:"Query:q1"的参数,在表达式中可以使用变量$q1,这个变量的值为当前请求中名为q1的Query参数的值。常量参数支持字符串、数字、布尔类型,如"Hello",'foo',100,-1,0.1,true,请参考参数类型与判断规则。支持以下
操作符:=,==:等于判断。<>,!=:不等于判断。>,>=,<,<=:比较判断。like、!like:相似判断,在字符串头尾的%可用于判断字符串相似,如$Query like 'Prefix%'。in_cidr、!in_cidr:判断IP地址的掩码,例如:$ClientIp in_cidr '47.89.XX.XX/24'。可使用
null来判断参数是否为空,如:$A == null或$A != null。可以使用
and、or、xor来组合连接不同的表达式,默认连接顺序为从右到左。可以用小括号
(,)来指定条件的优先级。使用
!(,)可以对括起来的表达式执行取反操作,如:!(1=1)结果为false。系统内置了一些函数,用于一些特殊场景的判断。
Random(): 产生一个0-1的浮点类型参数,用于蓝绿发布等一些需要随机的场合。Timestamp():返回以毫秒计数的Unix时间戳。TimeOfDay():按GMT时区,返回当前时间到当日零点的毫秒数。
3.2. 参数类型与判断规则
表达式中支持以下类型
STRING:字符串类型,支持单引号或双引号,如:"Hello"、'Hello'。NUMBER:整数或浮点数类型,如:1001,-1,0.1,-100.0。BOOLEAN:布尔类型,如:true、false。
对于
等于、不等于、比较操作符,不同类型的判断依据为:STRING:使用字符串顺序执行判断,例如:'123' > '1000'结果为true。'A123' > 'A120'结果为true。'' < 'a'结果为true。
NUMBER:使用数字大小进行判断。123 > 1000结果为false。100.0 == 100结果为true。
BOOLEAN:布尔值的判断依据为:true大于false。true == true结果为true。false == false结果为true。true > false结果为true。
对于
等于、不等于、比较操作符,如果左右两侧的参数类型不一致,参考以下的判断依据:STRING NUMBER: 如果左值能转换为NUMBER类型,则按照数字大小判断,否则按照字符串大小判断,例如:'100' = 100.0结果为true。'-100' > 0结果为false。
STRING BOOLEAN: 当左值能够转换为BOOLEAN类型时(忽略大小写等于true或false),按照BOOLEAN类型判断,否则除了!=判断外,其余的判断结果均为false,参考如下例子:'True' = true结果为true。'False' = false结果为true。'bad' = false结果为false。'bad' != false结果为true,对于左值非true或false的场景,除了!=操作符结果为true,其余结果均为false。'bad' != true结果为true。'0' > false结果为false。'0' <= false结果为false。
NUMBERBOOLEAN: 永远返回false。
null值可用于字段是否为空的判断,对于等于、不等于、比较操作符,判断依据为:当参数
$A为空时,$A == null结果为true,$A != null结果为false。空字符串
''不等于null时:'' == null结果为false,'' == ''结果为true。当用于
比较操作符时,任意一测值为null,则结果为false。
like,!like操作符,可用于字符串前缀、后缀、包含的判断,判断依据为 :表达式仅支持右值为
STRING常量的写法,如$Path like '/users/%'。右值两端的
'%'字符可用于支持前缀、后缀、与包含判断,如:前缀判断
$Path like '/users/%',$Path !like '/admin/%'。后缀判断
$q1 like '%search',$q1 !like '%.do'。包含判断
$ErrorCode like '%400%',$ErrorCode !like '%200%'。
当左值为非
NUMBER或BOOLEAN类型时,会转换为STRING格式后执行判断。当左值为空值
null时,结果为false。
in_cidr,!in_cidr表达式,可用于IP地址段掩码的判断,判断依据为:表达式仅支持右值为
STRING常量且符合IPv4或IPv6 CIDR格式的写法,如:$ClientIP in_cidr '10.0.0.0/8'$ClientIP !in_cidr '0:0:0:0:0:FFFF::/96'
当左值类型为
STRING时,会作为IPv4地址后进行判断。当左值类型为
NUMBER、BOOLEAN或为空时,结果为false。System:CaClientIp参数会返回客户端的IP地址,一般使用这种方式执行判断。
4. 使用案例
随机5%的几率:
Random() < 0.05判断当前API请求的是测试环境:
parameters:
stage: "System:CaStage"$CaStage = 'TEST'自定义参数中的UserName是Admin且来源IP在
47.47.XX.XX/24范围内。
parameters:
UserName: "Token:UserName"
ClientIp: "System:CaClientIp"$UserName = 'Admin' and $CaClientIp in_cidr '47.47.XX.XX/24'当前请求的用户ID是1001、1098、2011中的一个,且使用HTTPS协议请求。
parameters:
CaAppId: "System:CaAppId"
HttpSchema: "System:CaHttpSchema"$CaHttpScheme = 'HTTPS' and ($CaAppId = 1001 or $CaAppId = 1098 or $CaAppId = 2011)`当应答StatusCode=200,包体
json存在result_code且不为ok时。
parameters:
StatusCode: "StatusCode"
ResultCode: "BodyJsonField:$.result_code"$StatusCode = 200 and ($ResultCode <> null and $ResultCode <> 'ok')使用限制
单个插件中的参数定义个数不超过16个。
单个表达式的字符数不超过512个字符。
BodyJsonField对请求或应答包体的限制为16K Bytes,超过限制后将不会生效。