本文讲述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即可,不需要NameHeader
位置的参数,当用于请求阶段的插件时,读取来自客户端请求中的Header; 当用于应答阶段的插件时,读取来自后端应答中的HeaderParameter
位置的参数,仅用于请求阶段的插件,查找API定义中同名的参数,使用参数名
而非后端参数名
查找,当参数不存在时返回为null
Host
位置的参数,仅支持在泛域名参数提取,参考使用自定义域名调用API文档的3.2章节, 完整的Host请使用System:CaDomain
读取系统参数Path
返回为完整的请求路径,如果需要Path
位置的参数,请使用Parameter
位置的参数BodyJsonField
位置的参数,目前仅支持在错误码映射插件中使用,使用JSONPath
方式读取应答JSON包体的值,参考2.4. 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
,请参考3.2. 参数类型与判断规则支持以下
操作符
:=
,==
:等于判断<>
,!=
:不等于判断>
,>=
,<
,<=
:比较判断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
结果为false100.0 == 100
结果为true
BOOLEAN
:布尔值的判断依据为:true
大于false
true == true
结果为truefalse == false
结果为truetrue > 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')
5. 使用限制
单个插件中的参数定义个数不超过16个
单个表达式的字符数不超过512个字符
BodyJsonField对请求或应答包体的限制为16K Bytes, 超过限制后将不会生效