diff --git a/apisix/plugins/api-breaker.lua b/apisix/plugins/api-breaker.lua index bf10e0234870c..5ccf4404082a3 100644 --- a/apisix/plugins/api-breaker.lua +++ b/apisix/plugins/api-breaker.lua @@ -20,6 +20,8 @@ local plugin_name = "api-breaker" local ngx = ngx local math = math local error = error +local ipairs = ipairs + local shared_buffer = ngx.shared["plugin-".. plugin_name] if not shared_buffer then @@ -35,6 +37,25 @@ local schema = { minimum = 200, maximum = 599, }, + break_response_body = { + type = "string" + }, + break_response_headers = { + type = "array", + items = { + type = "object", + properties = { + key = { + type = "string", + minLength = 1 + }, + value = { + type = "string", + minLength = 1 + } + } + } + }, max_breaker_sec = { type = "integer", minimum = 3, @@ -158,6 +179,15 @@ function _M.access(conf, ctx) -- breaker if lasttime + breaker_time >= ngx.time() then + if conf.break_response_body then + if conf.break_response_headers then + for _, value in ipairs(conf.break_response_headers) do + local val = core.utils.resolve_var(value.value, ctx.var) + core.response.add_header(value.key, val) + end + end + return conf.break_response_code, conf.break_response_body + end return conf.break_response_code end diff --git a/docs/en/latest/plugins/api-breaker.md b/docs/en/latest/plugins/api-breaker.md index bf1d4a0951a49..9f561c9145f27 100644 --- a/docs/en/latest/plugins/api-breaker.md +++ b/docs/en/latest/plugins/api-breaker.md @@ -44,6 +44,8 @@ In an unhealthy state, when a request is forwarded to an upstream service and th | Name | Type | Requirement | Default | Valid | Description | | ----------------------- | ------------- | ----------- | -------- | --------------- | --------------------------------------------------------------------------- | | break_response_code | integer | required | | [200, ..., 599] | Return error code when unhealthy | +| break_response_body | string | optional | | | Return response body when unhealthy | +| break_response_headers | array[object] | optional | | | New headers for the response. The values in the header can contain Nginx variables like `$remote_addr` and `$balancer_ip`. This field is in effective only if `break_response_body` is configured. | | max_breaker_sec | integer | optional | 300 | >=3 | Maximum breaker time(seconds) | | unhealthy.http_statuses | array[integer] | optional | {500} | [500, ..., 599] | Status codes when unhealthy | | unhealthy.failures | integer | optional | 3 | >=1 | Number of consecutive error requests that triggered an unhealthy state | diff --git a/docs/zh/latest/plugins/api-breaker.md b/docs/zh/latest/plugins/api-breaker.md index 0230fc566e890..6672f8d4fa446 100644 --- a/docs/zh/latest/plugins/api-breaker.md +++ b/docs/zh/latest/plugins/api-breaker.md @@ -44,6 +44,8 @@ title: api-breaker | 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 | | ----------------------- | -------------- | ------ | ---------- | --------------- | -------------------------------- | | break_response_code | integer | 必须 | 无 | [200, ..., 599] | 不健康返回错误码 | +| break_response_body | string | 可选 | 无 | | 不健康返回报文 | +| break_response_headers | array[object] | 可选 | 无 | | 不健康返回报文头,这里可以设置多个。这个值能够以 `$var` 的格式包含 Nginx 变量,比如 `$remote_addr $balancer_ip`。该字段仅在 `break_response_body` 被配置时生效 | | max_breaker_sec | integer | 可选 | 300 | >=3 | 最大熔断持续时间 | | unhealthy.http_statuses | array[integer] | 可选 | {500} | [500, ..., 599] | 不健康时候的状态码 | | unhealthy.failures | integer | 可选 | 3 | >=1 | 触发不健康状态的连续错误请求次数 | diff --git a/t/plugin/api-breaker.t b/t/plugin/api-breaker.t index 1dc480cfa2f75..e1eccfb2b6b1f 100644 --- a/t/plugin/api-breaker.t +++ b/t/plugin/api-breaker.t @@ -458,6 +458,8 @@ breaker_time: 2 "plugins": { "api-breaker": { "break_response_code": 502, + "break_response_body": "{\"message\":\"breaker opened.\"}", + "break_response_headers": [{"key":"Content-Type","value":"application/json"},{"key":"Content-Type","value":"application/json+v1"}], "unhealthy": { "failures": 3 }, @@ -509,6 +511,10 @@ GET /api_breaker?code=500 ] --- error_code eval [200, 500, 503, 500, 500, 502] +--- response_headers eval +["Content-Type: text/plain", "Content-Type: text/html", "Content-Type: text/html", "Content-Type: text/html", "Content-Type: text/html", "Content-Type: application/json+v1"] +--- response_body_like eval +[".*", ".*", ".*", ".*", ".*", "{\"message\":\"breaker opened.\"}"] --- no_error_log [error]