ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Higress 网关错误响应格式化插件 gw-error-format 使用与实现原理指南

Higress 网关错误响应格式化插件 gw-error-format 使用与实现原理指南 Higress 网关错误响应格式化插件 gw-error-format 使用与实现原理指南【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higressgw-error-format是 Higress 提供的一款 Wasm 插件用于在网关尚未把请求转发到后端服务即错误响应由网关自身产生时精确匹配响应状态码与响应体并将其替换为自定义内容同时支持按需追加/覆盖响应头。通过本文你将掌握该插件的全部配置字段、部署方式、匹配规则细节以及其底层以x-envoy-upstream-service-time响应头区分网关自产错误与上游响应的核心判定机制。插件定位只改写网关自己犯的错在 Higress 网关的日常运维中有一类典型问题请求因鉴权失败、路由未命中、上游无健康节点等原因由Envoy 网关自身直接返回错误响应例如403 RBAC: access denied、503 no healthy upstream。这类响应的状态码与错误文案往往面向开发者而非终端用户格式不统一也无法承载业务自定义的错误语义如 JSON 化的错误码。gw-error-format插件正是为此设计它只对网关未转发到后端服务的响应生效将匹配到的状态码、响应体整体替换为业务自定义内容且不影响正常转发到上游后由后端返回的响应。这一点也是它与一般响应改写类插件最本质的区别。核心原理x-envoy-upstream-service-time判定机制理解该插件首先要理解它如何区分网关自产错误与上游响应当请求被成功转发到后端服务并拿到响应时Envoy 会在响应头中写入x-envoy-upstream-service-time记录上游处理耗时当请求在网关侧直接被拦截/拒绝鉴权失败、无健康上游、路由失败等响应头中不会携带该字段。插件的响应头处理逻辑main.go 中的onHttpResponseHeader会先尝试读取x-envoy-upstream-service-time响应头读取失败响应头不存在判定为网关自身产生的错误响应进入改写流程读取成功响应头存在判定为上游真实响应插件跳过改写并调用ctx.DontReadResponseBody()跳过响应体处理避免多余的性能开销。这一机制保证了插件对上游业务响应零侵入是配置和使用该插件时最需要理解的行为前提。配置字段详解插件配置以 JSON/YAML 结构注入完整字段如下依据 README.md 与 spec.yaml 中的 OpenAPI Schema名称数据类型填写要求默认值描述rulesarray of object必填-改写规则列表规则按声明顺序依次匹配rules[].match.statuscodestring必填-待匹配的响应状态码如403rules[].match.responsebodystring必填-待匹配的响应体精确匹配rules[].replace.statuscodestring必填-匹配成功后替换为的响应状态码rules[].replace.responsebodystring必填-匹配成功后替换为的响应体set_headerarray of object选填-添加/替换响应头每个元素为一个键值对对象几点实现层面的细节可对照源码验证必填校验parseConfigmain.go在插件启动解析配置时会逐一检查每条规则若match.statuscode或replace.statuscode为空直接返回错误missing match.statuscode in config/missing replace.statuscode in config插件启动失败。对应测试见 main_test.go 中TestParseConfig的无效配置用例断言OnPluginStartStatusFailed。精确字符串匹配match.statuscode与match.responsebody均为精确匹配源码中使用字符串比较官方 README_EN.md 也明确说明 Use exact strings for both status codes and response bodies。状态码需写成字符串形式如403而非403响应体则需与网关原始输出逐字符一致。替换状态码为字符串replace.statuscode同样以字符串形式配置写入时通过ReplaceHttpResponseHeader(:status, ...)完成。set_header的键值语义每个元素是单键值对象如- Content-Type: application/json;charsetUTF-8匹配成功后这些头会被添加到响应中若响应中已存在同名头则被覆盖。spec.yaml中set_header被声明为additionalProperties: string即值为字符串的对象数组。配置示例与逐条行为说明原文档给出的完整示例全局生效rules: - match: statuscode: 403 responsebody: RBAC: access denied replace: statuscode: 200 responsebody: {\code\:401,\message\:\User is not authenticated\} - match: statuscode: 503 responsebody: no healthy upstream replace: statuscode: 200 responsebody: {\code\:404,\message\:\No Healthy Service\} set_header: - Access-Control-Allow-Credentials: true - Access-Control-Allow-Origin: * - Access-Control-Allow-Headers: * - Access-Control-Allow-Methods: * - Access-Control-Expose-Headers: * - Content-Type: application/json;charsetUTF-8行为解读当某请求的响应状态码为403且响应体为RBAC: access denied时插件将状态码替换为200响应体替换为 JSON 字符串{code:401,message:User is not authenticated}当某请求的响应状态码为503且响应体为no healthy upstream时插件将状态码替换为200响应体替换为{code:404,message:No Healthy Service}一旦有规则的状态码匹配成功set_header中配置的响应头此处为跨域相关头与Content-Type会随响应一并下发。注意响应体匹配发生在状态码匹配之后。从源码调用链看响应头阶段先完成状态码替换随后才进入onHttpResponseBody对响应体做精确比对与替换。若状态码匹配但响应体不匹配状态码仍会被替换响应头处理逻辑独立于响应体这一点在配置多条规则时需留意规则之间的语义边界。关于响应体中 JSON 的写法responsebody的值是字符串因此 JSON 内容需按 YAML 字符串规则转义引号如示例中的\或使用单引号包裹整段 JSON如{code:503,message:service unavailable}参考 README_EN.md 示例。部署方式全局生效与路由级生效插件配置遵循 Higress 标准 WasmPlugin 声明方式需要将配置放入defaultConfig全局生效或matchRules按 Ingress 路由生效。以仓库内提供的完整示例 gw-error-format.yaml 为例示意镜像地址请按实际发布为准apiVersion: extensions.istio.io/v1alpha1 kind: WasmPlugin metadata: name: gw-error-format namespace: higress-system spec: selector: matchLabels: higress: higress-system-higress-gateway defaultConfig: rules: - match: statuscode: 200 responsebody: bar replace: statuscode: 401 responsebody: {\code\:401,\message\:\User is not authenticated\} - match: statuscode: 503 responsebody: no healthy upstream replace: statuscode: 200 responsebody: {\code\:404,\message\:\No Healthy Service\} set_header: - access-control-allow-credentials: true - access-control-allow-origin: * - access-control-expose-headers: * - content-type: application/json;charsetUTF-8 - custom-header: HelloWorld url: oci://docker.io/zhangjiahaol/envoy-plugin:gw-error-format-2.0.0配置作用域说明全局生效上述写法中配置放在defaultConfig下作用于当前网关实例的所有流量路由级生效如需仅对特定 Ingress/域名生效可将配置拆分到matchRules[].config中写法可参考 samples/wasmplugin/ingress-level-config.yaml 的结构matchRules下按ingress: [namespace/name]指定目标并注入config。此外spec.yamlplugins/release/console/gw-error-format/spec.yaml同时声明了插件级配置configSchema与路由级配置routeConfigSchema两套 JSON Schema说明该插件在 Higress 控制台配置场景下同时支持全局配置与按路由覆盖配置。插件当前版本为 1.0.1见 VERSION官方控制台收录的最小网关版本要求为 2.0.0gatewayMinVersion: 2.0.0。源码级实现深入三段式处理链路插件整体实现位于 main.go通过wrapper.SetCtx注册了三个钩子配置解析、响应头处理、响应体处理。整个处理链路如下parseConfig启动时 └─ 校验每条规则match.statuscode / replace.statuscode 必填 onHttpResponseHeader响应头阶段 ├─ 读取 :status 与 x-envoy-upstream-service-time ├─ 状态码命中规则 且 无 upstream-service-time 头 │ ├─ 移除 content-length响应体将变化长度头需失效 │ ├─ 替换 :status 为 replace.statuscode │ ├─ 遍历 set_header 添加/覆盖响应头 │ └─ 继续进入响应体处理 └─ 未命中 或 有 upstream-service-time 头 └─ DontReadResponseBody() 跳过响应体处理 onHttpResponseBody响应体阶段 ├─ 遍历规则对 bodyStr 做精确匹配 ├─ 命中ReplaceHttpResponseBody 替换为 replace.responsebody └─ 未命中保持原样各阶段关键实现细节parseConfigmain.go从 JSON 中读取set_header与rules数组规则校验只强制match.statuscode与replace.statuscode非空match.responsebody/replace.responsebody即便留空也可通过解析但按文档要求应填写否则无法完成响应体改写。onHttpResponseHeadermain.go使用switch currentStatuscode依次匹配每条规则的match.statuscode命中后通过proxywasm.GetHttpResponseHeader(x-envoy-upstream-service-time)二次确认是否网关自产错误。改写时先RemoveHttpResponseHeader(content-length)避免替换响应体后长度头失真再替换:status最后用ReplaceHttpResponseHeader逐个写入set_header。若匹配失败或存在上游耗时头则调用ctx.DontReadResponseBody()跳过响应体阶段保证性能。onHttpResponseBodymain.go对完整响应体字符串与各规则match.responsebody做精确比较命中即整体替换为replace.responsebody。测试用例行为契约的验证依据仓库提供了较为完整的单元测试main_test.go从测试断言可以反向确认插件的行为契约TestParseConfig验证基本配置、多规则配置、空配置、仅rules无set_header均能正常解析缺少match.statuscode或replace.statuscode的配置启动失败OnPluginStartStatusFailedTestOnHttpResponseHeader状态码 403 命中且无x-envoy-upstream-service-time头 → 状态码替换为 200custom-header、Content-Type等自定义头被写入状态码 403 命中但有x-envoy-upstream-service-time头 → 插件不生效状态码保持 403状态码不匹配如 404→ 保持原样空配置 → 保持原样TestOnHttpResponseBody响应体精确匹配则替换如RBAC: access denied→{code:401,...}不匹配则保持不变多规则场景下no healthy upstream按第二条规则替换为{code:404,...}TestCompleteFlow端到端验证状态码、响应体、自定义响应头三者同时生效的完整链路。这些用例与 README 描述完全一致可作为配置正确性的行为基准凡携带x-envoy-upstream-service-time头的响应即上游真实响应一律不被改写。典型使用场景与注意事项典型场景将网关鉴权失败如 RBAC403统一改写为业务约定的 JSON 错误结构便于前端统一解析将无健康上游503 no healthy upstream等基础设施错误转换为面向业务的友好提示避免暴露内部服务状态在改写的同时追加跨域响应头Access-Control-Allow-*解决网关直返错误时前端跨域读取不到错误详情的问题。注意事项插件只对网关自身生成的响应生效凡是成功转发并带x-envoy-upstream-service-time头的响应均不受影响因此不要指望用它改写上游返回的业务错误——如需改写上游响应应使用其他响应改写类插件状态码与响应体均为精确字符串匹配需先通过抓包/日志确认网关实际输出的状态码和错误文案大小写、空格、换行均需一致再编写match字段replace.statuscode建议使用合法的 HTTP 状态码示例中将错误替换为200属于业务定制行为错误信息转移到 JSON body 中是否采用需结合客户端契约评估当配置多条规则时规则按声明顺序依次尝试状态码替换与响应体替换是分阶段完成的若响应体未精确命中状态码可能已被替换配置时需保持match与replace的语义自洽响应体被替换后插件会自动移除原content-length头避免长度不一致导致协议错误。延伸阅读插件功能与配置说明plugins/wasm-go/extensions/gw-error-format/README.md、英文版 plugins/release/console/gw-error-format/README_EN.md核心实现plugins/wasm-go/extensions/gw-error-format/main.go行为验证测试plugins/wasm-go/extensions/gw-error-format/main_test.go完整 WasmPlugin 部署示例plugins/wasm-go/extensions/gw-error-format/gw-error-format.yaml控制台收录 Schema配置校验规则plugins/release/console/gw-error-format/spec.yamlWasmPlugin 全局/路由级配置结构参考samples/wasmplugin/default-config.yaml、samples/wasmplugin/ingress-level-config.yaml【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表