You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2022/05/26 02:41:39 UTC
[apisix] branch master updated: feat: allow customizing response in the plugin (#7128)
This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new ef9ba91a6 feat: allow customizing response in the plugin (#7128)
ef9ba91a6 is described below
commit ef9ba91a601d400ef4d43e0dd3378f1d98c3b7d9
Author: 罗泽轩 <sp...@gmail.com>
AuthorDate: Thu May 26 10:41:33 2022 +0800
feat: allow customizing response in the plugin (#7128)
Signed-off-by: spacewander <sp...@gmail.com>
---
apisix/plugin.lua | 20 ++++++++-
apisix/schema_def.lua | 11 +++++
docs/en/latest/terminology/plugin.md | 24 ++++++++++
docs/zh/latest/terminology/plugin.md | 24 ++++++++++
t/admin/plugins.t | 4 +-
t/plugin/plugin.t | 87 ++++++++++++++++++++++++++++++++++++
6 files changed, 167 insertions(+), 3 deletions(-)
diff --git a/apisix/plugin.lua b/apisix/plugin.lua
index da3b848f3..fc76b2546 100644
--- a/apisix/plugin.lua
+++ b/apisix/plugin.lua
@@ -142,6 +142,16 @@ local function load_plugin(name, plugins_list, plugin_type)
end
properties.disable = plugin_injected_schema.disable
+
+ if properties._meta then
+ core.log.error("invalid plugin [", name,
+ "]: found forbidden '_meta' field in the schema")
+ return
+ end
+
+ properties._meta = plugin_injected_schema._meta
+ -- new injected fields should be added under `_meta`
+
plugin.schema['$comment'] = plugin_injected_schema['$comment']
end
@@ -743,11 +753,19 @@ function _M.run_plugin(phase, plugins, api_ctx)
local phase_func = plugins[i][phase]
if phase_func then
plugin_run = true
- local code, body = phase_func(plugins[i + 1], api_ctx)
+ local conf = plugins[i + 1]
+ local code, body = phase_func(conf, api_ctx)
if code or body then
if is_http then
if code >= 400 then
core.log.warn(plugins[i].name, " exits with http status code ", code)
+
+ if conf._meta and conf._meta.error_response then
+ -- Whether or not the original error message is output,
+ -- always return the configured message
+ -- so the caller can't guess the real error
+ body = conf._meta.error_response
+ end
end
core.response.exit(code, body)
diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua
index 091785d37..767c2fa63 100644
--- a/apisix/schema_def.lua
+++ b/apisix/schema_def.lua
@@ -914,6 +914,17 @@ _M.plugin_injected_schema = {
["$comment"] = "this is a mark for our injected plugin schema",
disable = {
type = "boolean",
+ },
+ _meta = {
+ type = "object",
+ properties = {
+ error_response = {
+ oneOf = {
+ { type = "string" },
+ { type = "object" },
+ }
+ },
+ }
}
}
diff --git a/docs/en/latest/terminology/plugin.md b/docs/en/latest/terminology/plugin.md
index 7e94bf0b1..4bb12a4e3 100644
--- a/docs/en/latest/terminology/plugin.md
+++ b/docs/en/latest/terminology/plugin.md
@@ -72,6 +72,30 @@ A warning level log as shown below indicates that the request was rejected by th
ip-restriction exits with http status code 403
```
+## Plugin Common Configuration
+
+Some common configurations can be applied to the plugin configuration. For example,
+
+```json
+{
+ "jwt-auth": {
+ "_meta": {
+ "error_response": {
+ "message": "Missing credential in request"
+ }
+ }
+ }
+}
+```
+
+the configuration above means customizing the error response from the jwt-auth plugin to '{"message": "Missing credential in request"}'.
+
+### Plugin Common Configuration Under `_meta`
+
+| Name | Type | Description |
+|--------------|------|-------------|
+| error_response | string/object | Custom error response |
+
## Hot Reload
APISIX Plugins are hot-loaded. This means that there is no need to restart the service if you add, delete, modify plugins, or even if you update the plugin code. To hot-reload, you can send an HTTP request through the [Admin API](../admin-api.md):
diff --git a/docs/zh/latest/terminology/plugin.md b/docs/zh/latest/terminology/plugin.md
index daddd168e..c57767565 100644
--- a/docs/zh/latest/terminology/plugin.md
+++ b/docs/zh/latest/terminology/plugin.md
@@ -66,6 +66,30 @@ local _M = {
如果一个请求因为某个插件而被拒绝,会有类似这样的 warn 日志:`ip-restriction exits with http status code 403`。
+## 插件通用配置
+
+一些通用的配置可以应用于插件配置。比如说。
+
+````json
+{
+ "jwt-auth": {
+ "_meta": {
+ "error_response": {
+ "message": "Missing credential in request"
+ }
+ }
+ }
+}
+```
+
+上面的配置意味着将 jwt-auth 插件的错误响应自定义为 '{"message": "Missing credential in request"}'。
+
+### 在 `_meta` 下的插件通用配置
+
+| 名称 | 类型 | 描述 |
+|--------------|------|----------------|
+| error_response | string/object | 自定义错误响应 |
+
## 热加载
APISIX 的插件是热加载的,不管你是新增、删除还是修改插件,都不需要重启服务。
diff --git a/t/admin/plugins.t b/t/admin/plugins.t
index 9581c5389..2bfb5fee3 100644
--- a/t/admin/plugins.t
+++ b/t/admin/plugins.t
@@ -265,7 +265,7 @@ plugins:
}
}
--- response_body eval
-qr/\{"metadata_schema":\{"properties":\{"ikey":\{"minimum":0,"type":"number"\},"skey":\{"type":"string"\}\},"required":\["ikey","skey"\],"type":"object"\},"priority":0,"schema":\{"\$comment":"this is a mark for our injected plugin schema","properties":\{"disable":\{"type":"boolean"\},"i":\{"minimum":0,"type":"number"\},"ip":\{"type":"string"\},"port":\{"type":"integer"\},"s":\{"type":"string"\},"t":\{"minItems":1,"type":"array"\}\},"required":\["i"\],"type":"object"\},"version":0.1\}/
+qr/\{"metadata_schema":\{"properties":\{"ikey":\{"minimum":0,"type":"number"\},"skey":\{"type":"string"\}\},"required":\["ikey","skey"\],"type":"object"\},"priority":0,"schema":\{"\$comment":"this is a mark for our injected plugin schema","properties":\{"_meta":\{"properties":\{"error_response":\{"oneOf":\[\{"type":"string"\},\{"type":"object"\}\]\}\},"type":"object"\},"disable":\{"type":"boolean"\},"i":\{"minimum":0,"type":"number"\},"ip":\{"type":"string"\},"port":\{"type":"integer"\}, [...]
@@ -366,7 +366,7 @@ qr/\{"properties":\{"password":\{"type":"string"\},"username":\{"type":"string"\
}
}
--- response_body
-{"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"burst":{"minimum":0,"type":"integer"},"conn":{"exclusiveMinimum":0,"type":"integer"},"default_conn_delay":{"exclusiveMinimum":0,"type":"number"},"disable":{"type":"boolean"},"key":{"type":"string"},"key_type":{"default":"var","enum":["var","var_combination"],"type":"string"},"only_use_default_delay":{"default":false,"type":"boolean"}},"required":["conn","burst","default_conn_delay","key"] [...]
+{"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"_meta":{"properties":{"error_response":{"oneOf":[{"type":"string"},{"type":"object"}]}},"type":"object"},"burst":{"minimum":0,"type":"integer"},"conn":{"exclusiveMinimum":0,"type":"integer"},"default_conn_delay":{"exclusiveMinimum":0,"type":"number"},"disable":{"type":"boolean"},"key":{"type":"string"},"key_type":{"default":"var","enum":["var","var_combination"],"type":"string"},"only_use [...]
diff --git a/t/plugin/plugin.t b/t/plugin/plugin.t
index 009a51187..e45f5d5f7 100644
--- a/t/plugin/plugin.t
+++ b/t/plugin/plugin.t
@@ -219,3 +219,90 @@ GET /apisix/plugin/blah
}
--- response_body
ok
+
+
+
+=== TEST 7: plugin with custom error message
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/1',
+ ngx.HTTP_PUT,
+ [[{
+ "plugins": {
+ "jwt-auth": {
+ "_meta": {
+ "error_response": {
+ "message":"Missing credential in request"
+ }
+ }
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1980": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/hello"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- response_body
+passed
+
+
+
+=== TEST 8: verify, missing token
+--- request
+GET /hello
+--- error_code: 401
+--- response_body
+{"message":"Missing credential in request"}
+
+
+
+=== TEST 9: validate custom error message configuration
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+
+ for _, case in ipairs({
+ {input = true},
+ {input = {
+ error_response = true
+ }},
+ {input = {
+ error_response = "OK"
+ }},
+ }) do
+ local code, body = t('/apisix/admin/global_rules/1',
+ ngx.HTTP_PUT,
+ {
+ plugins = {
+ ["jwt-auth"] = {
+ _meta = case.input
+ }
+ }
+ }
+ )
+ if code >= 300 then
+ ngx.print(body)
+ else
+ ngx.say(body)
+ end
+ end
+ }
+ }
+--- response_body
+{"error_msg":"failed to check the configuration of plugin jwt-auth err: property \"_meta\" validation failed: wrong type: expected object, got boolean"}
+{"error_msg":"failed to check the configuration of plugin jwt-auth err: property \"_meta\" validation failed: property \"error_response\" validation failed: value should match only one schema, but matches none"}
+passed