-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: mocking plugin #5940
feat: mocking plugin #5940
Changes from 2 commits
befb95c
ff1b662
1c38b88
2f09041
c5c7449
ab7dd01
8b15af7
4a27281
cefcaf2
41df69a
f807386
f86fd49
0a02f27
a351ded
9848555
9190d27
27d6d1b
439cf14
0c296b5
0d92b43
5fb3647
a62f7a8
e66a680
db37e2d
71e9af1
a42a7fe
67e5496
ebfe46f
b894f95
1454033
6ff7f11
ce39d6c
7f900bb
08a0c55
6fb6b0c
8f374f3
514f0af
bebc44a
6fd29c6
e525a84
ed9ae66
10fdc1d
d693611
968fdb2
43ac0de
5a54066
288f7e0
49fdd59
7da4aa6
2f2cffc
f5d9529
9d511c6
f87bf28
65447a2
95c7678
e88b7d5
6f7a256
396d2a9
9e0b57b
e7cfd2f
45047e5
502a69b
b1b789c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
-- | ||
-- Licensed to the Apache Software Foundation (ASF) under one or more | ||
-- contributor license agreements. See the NOTICE file distributed with | ||
-- this work for additional information regarding copyright ownership. | ||
-- The ASF licenses this file to You under the Apache License, Version 2.0 | ||
-- (the "License"); you may not use this file except in compliance with | ||
-- the License. You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
-- | ||
local core = require("apisix.core") | ||
local ngx = ngx | ||
local plugin_name = "mocking" | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
local schema = { | ||
type = "object", | ||
properties = { | ||
response_schema = { type = "object" } | ||
}, | ||
required = { "response_schema" } | ||
} | ||
|
||
local _M = { | ||
version = 0.1, | ||
priority = 9900, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget to update the priority in the code |
||
name = plugin_name, | ||
schema = schema, | ||
} | ||
|
||
function _M.check_schema(conf) | ||
local ok, err = core.schema.check(schema, conf) | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if not ok then | ||
return false, err | ||
end | ||
|
||
return true, nil | ||
end | ||
|
||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
function _M.access(conf) | ||
local output = gen_object(conf.response_schema) | ||
ngx.header["Content-Type"] = "application/json" | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return 200, core.utils.resolve_var(core.json.encode(output)) | ||
end | ||
|
||
function gen_object(property) | ||
local output = {} | ||
if property.properties == nil then | ||
return output | ||
end | ||
for k, v in pairs(property.properties) do | ||
local type = string.lower(v.type) | ||
if type == "array" then | ||
output[k] = gen_array(v) | ||
elseif type == "object" then | ||
output[k] = gen_object(v) | ||
else | ||
output[k] = get_base(v) | ||
end | ||
end | ||
return output | ||
end | ||
|
||
function gen_array(property) | ||
local output = {} | ||
if property.items == nil then | ||
return nil | ||
end | ||
local v = property.items | ||
local n = math.random(1, 3) | ||
local type = string.lower(v.type) | ||
for i = 1, n do | ||
if type == "array" then | ||
table.insert(output, gen_array(v)) | ||
elseif type == "object" then | ||
table.insert(output, gen_object(v)) | ||
else | ||
table.insert(output, get_base(v)) | ||
end | ||
end | ||
return output | ||
end | ||
|
||
function get_base(property) | ||
local type = string.lower(property.type) | ||
local example = property.example | ||
if type == "string" then | ||
return gen_string(example) | ||
elseif type == "number" then | ||
return gen_number(example) | ||
elseif type == "integer" then | ||
return gen_integer(example) | ||
elseif type == "boolean" then | ||
return gen_boolean(example) | ||
end | ||
return nil | ||
end | ||
|
||
function gen_string(example) | ||
if example ~= nil and type(example) == "string" then | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return example | ||
end | ||
local n = math.random(1, 10) | ||
local list = {} | ||
for i = 1, n do | ||
table.insert(list, string.char(math.random(97, 122))) | ||
end | ||
return table.concat(list) | ||
end | ||
|
||
function gen_number(example) | ||
if example ~= nil and type(example) == "number" then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same and take care of similar rest of them |
||
return example | ||
end | ||
return math.random() * 10000 | ||
end | ||
|
||
function gen_integer(example) | ||
if example ~= nil and type(example) == "number" then | ||
return math.floor(example) | ||
end | ||
return math.random(1, 10000) | ||
end | ||
|
||
function gen_boolean(example) | ||
if example ~= nil and type(example) == "boolean" then | ||
return example | ||
end | ||
local r = math.random(0, 2) | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if r == 0 then | ||
return false | ||
end | ||
return true | ||
end | ||
|
||
return _M | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
--- | ||
title: limit-req | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--- | ||
|
||
<!-- | ||
# | ||
# Licensed to the Apache Software Foundation (ASF) under one or more | ||
# contributor license agreements. See the NOTICE file distributed with | ||
# this work for additional information regarding copyright ownership. | ||
# The ASF licenses this file to You under the Apache License, Version 2.0 | ||
# (the "License"); you may not use this file except in compliance with | ||
# the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
--> | ||
|
||
## 目录 | ||
|
||
- [简介](#简介) | ||
- [属性](#属性) | ||
- [示例](#示例) | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- [如何在 `route` 或 `service` 上使用](#如何在`route`或`service`上使用) | ||
- [如何在 `consumer` 上使用](#如何在`consumer`上使用) | ||
- [移除插件](#移除插件) | ||
|
||
## 简介 | ||
|
||
Mock API插件,绑定该插件后将随机返回指定格式的mock数据,不再转发到后端。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add space around English word |
||
|
||
## 属性 | ||
|
||
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 | | ||
| ------------- | ------- | ------ | ------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| response_schema | object | 必须 | | | 响应的json schema对象。具体结构看后文说明。 | | ||
支持的字段类型:string,number,integer,boolean,object,array。 | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
基础数据类型(string,number,integer,boolean)可通过配置example属性指定生成的响应值,未配置时随机返回。 | ||
Drery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
以下是一个json schema实例: | ||
```json | ||
{ | ||
"properties":{ | ||
"field0":{ | ||
"example":"abcd", | ||
"type":"string" | ||
}, | ||
"field1":{ | ||
"example":123.12, | ||
"type":"number" | ||
}, | ||
"field3":{ | ||
"properties":{ | ||
"field3_1":{ | ||
"type":"string" | ||
}, | ||
"field3_2":{ | ||
"properties":{ | ||
"field3_2_1":{ | ||
"example":true, | ||
"type":"boolean" | ||
}, | ||
"field3_2_2":{ | ||
"items":{ | ||
"example":155.55, | ||
"type":"integer" | ||
}, | ||
"type":"array" | ||
} | ||
}, | ||
"type":"object" | ||
} | ||
}, | ||
"type":"object" | ||
}, | ||
"field2":{ | ||
"items":{ | ||
"type":"string" | ||
}, | ||
"type":"array" | ||
} | ||
}, | ||
"type":"object" | ||
} | ||
``` | ||
以下为该json schema可能生成的返回对象: | ||
```json | ||
{ | ||
"field1": 123.12, | ||
"field3": { | ||
"field3_1": "LCFE0", | ||
"field3_2": { | ||
"field3_2_1": true, | ||
"field3_2_2": [ | ||
155, | ||
155 | ||
] | ||
} | ||
}, | ||
"field0": "abcd", | ||
"field2": [ | ||
"sC" | ||
] | ||
} | ||
``` | ||
|
||
## 示例 | ||
|
||
### 如何在`route`或`service`上使用 | ||
|
||
这里以`route`为例(`service`的使用是同样的方法),在指定的 `route` 上启用 `mocking` 插件。 | ||
|
||
```shell | ||
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
"uri": "/index.html", | ||
"plugins": { | ||
"mocking": { | ||
"response_schema": { | ||
"properties":{ | ||
"field0":{ | ||
"example":"abcd", | ||
"type":"string" | ||
}, | ||
"field1":{ | ||
"example":123.12, | ||
"type":"number" | ||
}, | ||
"field3":{ | ||
"properties":{ | ||
"field3_1":{ | ||
"type":"string" | ||
}, | ||
"field3_2":{ | ||
"properties":{ | ||
"field3_2_1":{ | ||
"example":true, | ||
"type":"boolean" | ||
}, | ||
"field3_2_2":{ | ||
"items":{ | ||
"example":155.55, | ||
"type":"integer" | ||
}, | ||
"type":"array" | ||
} | ||
}, | ||
"type":"object" | ||
} | ||
}, | ||
"type":"object" | ||
}, | ||
"field2":{ | ||
"items":{ | ||
"type":"string" | ||
}, | ||
"type":"array" | ||
} | ||
}, | ||
"type":"object" | ||
} | ||
} | ||
}, | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:1980": 1 | ||
} | ||
} | ||
}' | ||
``` | ||
|
||
## 移除插件 | ||
|
||
当你想去掉 mocking 插件的时候,很简单,在插件的配置中把对应的 json 配置删除即可,无须重启服务,即刻生效: | ||
|
||
```shell | ||
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' | ||
{ | ||
"methods": ["GET"], | ||
"uri": "/index.html", | ||
"upstream": { | ||
"type": "roundrobin", | ||
"nodes": { | ||
"127.0.0.1:1980": 1 | ||
} | ||
} | ||
}' | ||
``` | ||
|
||
现在就已经移除了 mocking 插件了。其他插件的开启和移除也是同样的方法。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's sort the statements to make the
require
in a group.