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 2021/09/28 02:17:13 UTC
[apisix] branch master updated: feat: add rejected_message support
for plugin request-validation (#5122)
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 76540a5 feat: add rejected_message support for plugin request-validation (#5122)
76540a5 is described below
commit 76540a57f5800d74b4ceb5099f1b5132bf05e0ef
Author: leslie <59...@users.noreply.github.com>
AuthorDate: Tue Sep 28 10:17:08 2021 +0800
feat: add rejected_message support for plugin request-validation (#5122)
---
apisix/plugins/request-validation.lua | 33 ++-
docs/en/latest/plugins/request-validation.md | 43 +++-
docs/zh/latest/plugins/request-validation.md | 43 +++-
t/plugin/request-validation.t | 293 +++++++++++++++++++++++----
4 files changed, 338 insertions(+), 74 deletions(-)
diff --git a/apisix/plugins/request-validation.lua b/apisix/plugins/request-validation.lua
index a2af3cb..bdd26fa 100644
--- a/apisix/plugins/request-validation.lua
+++ b/apisix/plugins/request-validation.lua
@@ -17,27 +17,20 @@
local core = require("apisix.core")
local plugin_name = "request-validation"
local ngx = ngx
-local io = io
+local io = io
local req_read_body = ngx.req.read_body
local req_get_body_data = ngx.req.get_body_data
local schema = {
type = "object",
+ properties = {
+ header_schema = {type = "object"},
+ body_schema = {type = "object"},
+ rejected_msg = {type = "string", minLength = 1, maxLength = 256}
+ },
anyOf = {
- {
- title = "Body schema",
- properties = {
- body_schema = {type = "object"}
- },
- required = {"body_schema"}
- },
- {
- title = "Header schema",
- properties = {
- header_schema = {type = "object"}
- },
- required = {"header_schema"}
- }
+ {required = {"header_schema"}},
+ {required = {"body_schema"}}
}
}
@@ -82,7 +75,7 @@ function _M.rewrite(conf)
local ok, err = core.schema.check(conf.header_schema, headers)
if not ok then
core.log.error("req schema validation failed", err)
- return 400, err
+ return 400, conf.rejected_msg or err
end
end
@@ -94,11 +87,11 @@ function _M.rewrite(conf)
if not body then
local filename = ngx.req.get_body_file()
if not filename then
- return 500
+ return 500, conf.rejected_msg
end
local fd = io.open(filename, 'rb')
if not fd then
- return 500
+ return 500, conf.rejected_msg
end
body = fd:read('*a')
end
@@ -111,13 +104,13 @@ function _M.rewrite(conf)
if not req_body then
core.log.error('failed to decode the req body', error)
- return 400, error
+ return 400, conf.rejected_msg or error
end
local ok, err = core.schema.check(conf.body_schema, req_body)
if not ok then
core.log.error("req schema validation failed", err)
- return 400, err
+ return 400, conf.rejected_msg or err
end
end
end
diff --git a/docs/en/latest/plugins/request-validation.md b/docs/en/latest/plugins/request-validation.md
index 94b651f..a474ae6 100644
--- a/docs/en/latest/plugins/request-validation.md
+++ b/docs/en/latest/plugins/request-validation.md
@@ -39,10 +39,13 @@ For more information on schema, refer to [JSON schema](https://github.com/api7/j
## Attributes
-| Name | Type | Requirement | Default | Valid | Description |
-| ------------- | ------ | ----------- | ------- | ----- | -------------------------- |
-| header_schema | object | optional | | | schema for the header data |
-| body_schema | object | optional | | | schema for the body data |
+> Note that at least one of `header_schema` and `body_schema` must be filled in.
+
+| Name | Type | Requirement | Default | Valid | Description |
+| ---------------- | ------ | ----------- | ------- | ----- | -------------------------- |
+| header_schema | object | optional | | | schema for the header data |
+| body_schema | object | optional | | | schema for the body data |
+| rejected_message | string | optional | | | the custom rejected message |
## How To Enable
@@ -60,7 +63,8 @@ curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f13
"properties": {
"required_payload": {"type": "string"},
"boolean_payload": {"type": "boolean"}
- }
+ },
+ "rejected_message": "customize reject message"
}
}
},
@@ -82,7 +86,7 @@ curl --header "Content-Type: application/json" \
http://127.0.0.1:9080/get
```
-If the schema is violated the plugin will yield a `400` bad request.
+If the schema is violated the plugin will yield a `400` bad request with the reject response.
## Disable Plugin
@@ -252,3 +256,30 @@ curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f13
}
}
```
+
+**Custom rejected message:**
+
+```json
+{
+ "uri": "/get",
+ "plugins": {
+ "request-validation": {
+ "body_schema": {
+ "type": "object",
+ "required": ["required_payload"],
+ "properties": {
+ "required_payload": {"type": "string"},
+ "boolean_payload": {"type": "boolean"}
+ },
+ "rejected_message": "customize reject message"
+ }
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:8080": 1
+ }
+ }
+}
+```
diff --git a/docs/zh/latest/plugins/request-validation.md b/docs/zh/latest/plugins/request-validation.md
index f9ab2c4..c332bf4 100644
--- a/docs/zh/latest/plugins/request-validation.md
+++ b/docs/zh/latest/plugins/request-validation.md
@@ -38,10 +38,13 @@ title: request-validation
## 属性
-| Name | Type | Requirement | Default | Valid | Description |
-| ------------- | ------ | ----------- | ------- | ----- | --------------------------------- |
-| header_schema | object | 可选 | | | `header` 数据的 `schema` 数据结构 |
-| body_schema | object | 可选 | | | `body` 数据的 `schema` 数据结构 |
+> 注意, `header_schema` 与 `body_schema` 至少填写其中一个
+
+| Name | Type | Requirement | Default | Valid | Description |
+| ---------------- | ------ | ----------- | ------- | ----- | --------------------------------- |
+| header_schema | object | 可选 | | | `header` 数据的 `schema` 数据结构 |
+| body_schema | object | 可选 | | | `body` 数据的 `schema` 数据结构 |
+| rejected_message | string | 可选 | | | 自定义拒绝信息 |
## 如何启用
@@ -59,7 +62,8 @@ curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f13
"properties": {
"required_payload": {"type": "string"},
"boolean_payload": {"type": "boolean"}
- }
+ },
+ "rejected_message": "customize reject message"
}
}
},
@@ -81,7 +85,7 @@ curl --header "Content-Type: application/json" \
http://127.0.0.1:9080/get
```
-如果 `Schema` 验证失败,将返回 `400 bad request` 错误。
+如果 `Schema` 验证失败,将返回 `400` 状态码与相应的拒绝信息。
## 禁用插件
@@ -250,3 +254,30 @@ curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f13
}
}
```
+
+**自定义拒绝信息:**
+
+```json
+{
+ "uri": "/get",
+ "plugins": {
+ "request-validation": {
+ "body_schema": {
+ "type": "object",
+ "required": ["required_payload"],
+ "properties": {
+ "required_payload": {"type": "string"},
+ "boolean_payload": {"type": "boolean"}
+ },
+ "rejected_message": "customize reject message"
+ }
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:8080": 1
+ }
+ }
+}
+```
diff --git a/t/plugin/request-validation.t b/t/plugin/request-validation.t
index f870768..35edd03 100644
--- a/t/plugin/request-validation.t
+++ b/t/plugin/request-validation.t
@@ -61,9 +61,8 @@ done
}
--- request
GET /t
---- response_body
-object matches none of the requireds: ["body_schema"] or ["header_schema"]
-done
+--- response_body_like eval
+qr/object matches none of the requireds/
--- no_error_log
[error]
@@ -375,8 +374,6 @@ hello1 world
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -415,8 +412,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -455,8 +450,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -495,8 +488,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -535,8 +526,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -575,8 +564,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -615,8 +602,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -655,8 +640,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -787,8 +770,6 @@ qr/table expected, got string/
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -881,8 +862,6 @@ qr/table expected, got string/
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -939,8 +918,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -979,8 +956,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1019,8 +994,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1059,8 +1032,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1099,8 +1070,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1139,8 +1108,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1179,8 +1146,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1219,8 +1184,6 @@ passed
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1351,8 +1314,6 @@ qr/table expected, got string/
GET /t
--- response_body
passed
---- error_code chomp
-200
--- no_error_log
[error]
@@ -1445,7 +1406,255 @@ qr/table expected, got string/
GET /t
--- response_body
passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 35: add route (test request validation `header_schema.required` success with custom reject 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": {
+ "request-validation": {
+ "header_schema": {
+ "type": "object",
+ "properties": {
+ "test": {
+ "type": "string",
+ "enum": ["a", "b", "c"]
+ }
+ },
+ "required": ["test"]
+ },
+ "rejected_msg": "customize reject message for header_schema.required"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/opentracing"
+ }]])
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 36: use empty header to hit `header_schema.required with custom reject message` rule
+--- request
+GET /opentracing
+--- error_code: 400
+--- response_body chomp
+customize reject message for header_schema.required
+--- error_log eval
+qr/schema validation failed/
+
+
+
+=== TEST 37: use bad header value to hit `header_schema.required with custom reject message` rule
+--- request
+GET /opentracing
+--- more_headers
+test: abc
+--- error_code: 400
+--- response_body chomp
+customize reject message for header_schema.required
+--- error_log eval
+qr/schema validation failed/
+
+
+
+=== TEST 38: pass `header_schema.required with custom reject message` rule
+--- request
+GET /opentracing
+--- more_headers
+test: a
+--- error_code: 200
+--- response_body eval
+qr/opentracing/
+--- no_error_log
+[error]
+
+
+
+=== TEST 39: add route (test request validation `body_schema.required` success with custom reject 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": {
+ "request-validation": {
+ "body_schema": {
+ "type": "object",
+ "properties": {
+ "test": {
+ "type": "string",
+ "enum": ["a", "b", "c"]
+ }
+ },
+ "required": ["test"]
+ },
+ "rejected_msg": "customize reject message for body_schema.required"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/opentracing"
+ }]])
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 40: use empty body to hit `body_schema.required with custom reject message` rule
+--- request
+GET /opentracing
+--- error_code: 500
+--- response_body chomp
+customize reject message for body_schema.required
+--- no_error_log
+[error]
+
+
+
+=== TEST 41: use bad body value to hit `body_schema.required with custom reject message` rule
+--- request
+POST /opentracing
+{"test":"abc"}
+--- error_code: 400
+--- response_body chomp
+customize reject message for body_schema.required
+--- error_log eval
+qr/schema validation failed/
+
+
+
+=== TEST 42: pass `body_schema.required with custom reject message` rule
+--- request
+POST /opentracing
+{"test":"a"}
+--- error_code: 200
+--- response_body eval
+qr/opentracing/
+--- no_error_log
+[error]
+
+
+
+=== TEST 43: add route (test request validation `header_schema.required` failure with custom reject 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": {
+ "request-validation": {
+ "header_schema": {
+ "type": "object",
+ "properties": {
+ "test": {
+ "type": "string",
+ "enum": ["a", "b", "c"]
+ }
+ },
+ "required": ["test"]
+ },
+ "rejected_msg": "customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message customize reject message"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/plugin/request/validation"
+ }]])
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body_like eval
+qr/string too long/
--- error_code chomp
-200
+400
+--- no_error_log
+[error]
+
+
+
+=== TEST 44: add route (test request validation schema with custom reject message only)
+--- 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": {
+ "request-validation": {
+ "rejected_message": "customize reject message"
+ }
+ },
+ "upstream": {
+ "nodes": {
+ "127.0.0.1:1982": 1
+ },
+ "type": "roundrobin"
+ },
+ "uri": "/plugin/request/validation"
+ }]])
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body_like eval
+qr/object matches none of the requireds/
+--- error_code chomp
+400
--- no_error_log
[error]