错误码映射插件

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

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网关的系统错误码与系统错误信息,请参考错误代码表文档。

  • 使用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网关系统错误码出现在网关的检查、校验、流控、插件处理等场合,参考错误代码表文档,使用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}"

4.2 应答body映射

#
# 这个例子用于给前端返回定制的json错误body
---
# 指定映射参数
parameters:
  statusCode: "StatusCode"
  resultCode: "Header:X-Ca-Error-Code"
  requestId: "Header:X-Ca-Request-Id"
  errorMessage: "Header:X-Ca-Error-Message"

# 映射条件
errorCondition: "$statusCode != 200"
# 错误码字段
errorCode: "resultCode"
# 映射项
mappings:
  - code: "I400MH"
    statusCode: 200
    responseHeaders:
        Content-Type: "application/xml"
        X-Ca-Error-Message: ""
        X-Ca-Error-Code: ""
    responseBody: |
        {
            "code":"89",
            "message":"${errorMessage}",
            "resultCode":"${resultCode}"
            
        }

5. 使用限制

  • 参数定义个数不超过16个。

  • 单个表达式的字符数不超过512个字符。

  • BodyJsonField位置的字段对应答包体的限制为16380 Bytes, 超过后直接返回空值。

  • 插件配置大小限制为50KB

  • mappings中以condition方式配置映射记录不超过20条。