错误码映射插件用于将后端应答中返回的非正常请求,映射为客户端期望的错误应答的场景

1. 概述

错误码映射插件用于将后端应答中返回的非正常请求,映射为客户端期望的错误应答的场景。

2. 快速开始

请先参考下面的例子, 某后端的的返回中, HTTP应答码为200, 但错误信息包含在包体中json字段中。

HTTP 200 OK
Content-Type:application/json

{"req_msg_id":"d02afa56394f4588832bed46614e1772","result_code":"ROLE_NOT_EXISTS"}
  • 在这个场景中,客户端期望得到非200的应答,但希望通过不修改后端的方式实现
HTTP 404 
X-Ca-Error-Message: Role Not Exists, ResultId=d02afa56394f4588832bed46614e1772

针对描述的中的场景,我们可以按照如下的方式配置错误码映射插件

---
# 参与映射的字段
parameters:
  statusCode: "StatusCode"
  resultCode: "BodyJsonField:$.result_code"
  resultId: "BodyJsonField:$.req_msg_id"
# 映射条件
errorCondition: "$statusCode = 200 and $resultCode <> 'OK'"
# 错误码字段
errorCode: "resultCode"
# 映射项
mappings:
  - code: "ROLE_NOT_EXISTS"
    statusCode: 404
    errorMessage: "Role Not Exists, RequestId=${resultId}"
  - code: "INVALID_PARAMETER"
    statusCode: 400
    errorMessage: "Invalid Parameter, RequestId=${resultId}"
# 默认映射(可选)
defaultMapping:
  statusCode: 500
  errorMessage: "Unknown Error, ${resultCode}, RequestId=${resultId}"

在这个例子中,我们将后端应答码以及后端应答JSON包体中的result_code字段设置为了应答条件,如果后端应答码为200,但result_code字段不等于'OK'时,开始执行错误码映射,这个例子中,我们使用result_code作为错误码字段执行映射,配置了两个错误码:当ROLE_NOT_EXISTS会返回给客户端404应答,而INVALID_PARAMETER会返回给客户端400应答,其他错误码返回500应答。

3. 插件配置与映射规则

3.1. 插件配置

错误映射插件配置使用jsonyaml格式配置,各个字段的详细说明如下:

  • parameters(必选): 下面配置参与映射的字段, 以map方式配置, 参考文档参数与条件表达式
  • errorCondition(必选): 应答是否属于错误应答的条件表达式,当执行结果为true时,执行映射
  • errorCode(可选): 用于指定错误代码字段, 用于匹配mappings映射列表中的code字段
  • mappings(必选): 用于指定映射记录列表, 网关将会用符合错误代码错误条件记录重新构造返回应答,详细字段为
    • code(可选): 唯一,设置这个字段是codeParameter字段为必选, 当错误代码code字段一致时,执行当前映射记录
    • condition(可选): 错误条件表达式, 当表达式演算为true时,执行当前映射记录
    • statusCode(必选): 用于指定当前映射记录的HTTP返回码
    • errorMessage(可选): 用于指定当前映射记录的错误信息,体现在应答的X-Ca-Error-Message头及日志的errorMessage字段中
    • responseHeaders(可选): 以Map方式配置,用于设置当前映射记录的应答头
    • responseBody(可选): 用于覆写当前映射记录的应答包体
  • defaultMapping(可选): 默认映射记录,如果mappings中的所有记录均未命中, 则使用本条记录作为应答
    • statusCode(必选): 用于指定当前映射记录的HTTP返回码
    • errorMessage(可选): 用于指定当前映射记录的错误信息,体现在应答的X-Ca-Error-Message头及日志的errorMessage字段中
    • responseHeaders(可选): 以Map方式配置,用于设置当前映射记录的应答头
    • responseBody(可选): 用于覆写当前映射记录的应答包体

配置规则:

  • mappingCondition, mappings[].condition中的条件表达式使用的参数,与parameters字段中定义的字段必须对应,否则会报错,关于参数定义与条件表达式,参考参数与条件表达式文档
  • errorCode字段中使用的参数必须为parameters中定义的字段
  • mappings列表记录中的codecondition必须配置其中的一个,当配置code时值必须唯一,当配置condition时,将按照配置顺序执行,越靠前的优先级越高
  • errorMessage,responseBody可以使用类似"${Code}: ${Message}"的格式对消息进行模板替换, 字段取值来自parameters中提取到的值
  • responseHeaders的值,也可以使用${Message}的方式执行模板替换
  • responseBody不配置时, 透传后端应答
  • responseHeaders不配置时,透传后端应答的Headers, 否则使用配置键值对覆盖后端应答的Header,当值配置为''时,删除对应的Header
  • defaultMapping没有配置时,错误码映射不生效,透传后端应答

3.2. 映射参数

映射参数可通过如下的方式在parameters参数中配置为键值对,其中键作为变量名定义,值可以使用Location:Name的方式配置,表示从当前应答或系统上下文的特定位置中读取。

---
# 参与映射的字段
parameters:
  statusCode: "StatusCode"
  resultCode: "BodyJsonField:$.result_code"
  resultId: "BodyJsonField:$.req_msg_id"

错误码映射目前支持以下位置的参数,具体参数描述请参考参数与条件表达式文档。

位置名称 适用范围 说明
StatusCode 应答 后端的HTTP应答码,如: 200, 400
ErrorCode 应答 API网关系统错误码
ErrorMessage 应答 API网关系统错误消息
Header 应答 使用Header:{Name}获取名字为{Name}的HTTP头的第一个值
BodyJsonField 应答* 使用BodyJson:{JPath}JSONPath方式获取请求/应答包体中的JSON字段值
System 应答 使用System:{Name}获取名字为{Name}的系统参数值
Token 应答 当处于jwt,oauth2授权场景是,使用Token:{Name}获取token中名字为{Name}的值
  • ErrorCodeErrorMessage会返回API网关的系统错误码与系统错误信息,请参考API网关系统错误码文档。
  • 使用BodyJsonField可以使用JSONPath来提取后端返回json的值, 但如果后端应答的包体大小超过15360 Bytes则这个字段将会无法提取到值,得到的是空值null

3.3. 执行规则

错误码映射插件会按照如下的顺序执行:

    1. 根据parameters中配置的参数列表,从应答及系统上下文中获取当前的参数表
    1. 依据步骤1得到的参数表,执行errorCondition中配置的条件表达式,为true则继续执行,false不生效
    1. 如果配置了errorCode字段, 则获取errorCode字段的值, 并寻找与mappingscode匹配的映射记录,
    1. 如果步骤3没有匹配到映射记录,则依次执行mappings字段配置了condition映射记录
    1. 如果步骤3或4中匹配到了映射记录,根据对应的配置构造应答,否则构造默认应答

3.4. 系统错误的映射及日志

  • API网关系统错误码出现在网关的检查、校验、流控、插件处理等场合,参考API网关系统错误码文档,使用ErrorCode作为映射参数,可以支持对系统错误码的映射,可用于诸如:客户端仅支持200应答,但希望将被限流的429应答映射为200应答的场景。
  • 当出现系统错误时,位置为StatusCode, Header, BodyJsonField等来自应答的字段取值都将为null,在写条件表达式时需要注意,未出现系统错误时ErrorCode位置的取值为OK
  • API网关的系统错误码会出现在X-Ca-Error-Code应答头及日志的errorCode字段中,这个值不会被错误码映射插件改写。
  • 日志中的statusCode字段记录的是网关递送给客户端的应答码的值,会被错误码映射插件改写。

4. 配置示例

4.1. 映射包体错误码

映射

---
# 参与映射的字段
parameters:
  statusCode: "StatusCode"
  resultCode: "BodyJsonField:$.result_code"
  resultId: "BodyJsonField:$.req_msg_id"
# 映射条件
errorCondition: "$statusCode = 200 and $resultCode <> 'OK'"
# 错误码字段
errorCode: "resultCode"
# 映射项
mappings:
  - code: "ROLE_NOT_EXISTS"
    statusCode: 404
    errorMessage: "Role Not Exists, RequestId=${resultId}"
  - code: "INVALID_PARAMETER"
    statusCode: 400
    errorMessage: "Invalid Parameter, RequestId=${resultId}"
# 默认映射(可选)
defaultMapping:
  statusCode: 500
  errorMessage: "Unknown Error, ${resultCode}, RequestId=${resultId}"

5. 使用限制

  • 参数定义个数不超过16个。
  • 单个表达式的字符数不超过512个字符。
  • BodyJsonField位置的字段对应答包体的限制为16380 Bytes, 超过后直接返回空值。
  • 插件配置大小限制为16380字符的文本。
  • mappings中以condition方式配置映射记录不超过20条。