Apache APISIX mocking 插件实战:用 JSON Schema 生成随机 Mock 数据
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
mocking是 Apache APISIX 内置的 API 模拟插件:当请求命中配置了该插件的路由时,网关会直接返回按指定格式(固定字符串或 JSON Schema 随机生成)生成的模拟数据,请求不会转发到上游服务。本文以 中文官方文档 为主体,结合 插件源码 与 测试用例,完整讲解该插件的全部属性、随机数据生成原理、启用与删除的完整操作,以及响应头、内置变量等进阶用法,帮助你在一分钟内为前端联调、接口压测或演示环境搭出可用的 Mock 服务。
插件核心原理
从 mocking.lua 源码可以看到,该插件在 APISIX 插件链中拥有priority = 10900的高优先级(见 mocking.lua),且仅在access阶段执行主逻辑(见 mocking.lua):
- 若配置了
response_example,直接以该字符串作为响应 Body; - 否则按
response_schema递归生成随机数据; - 随后设置
Content-Type、x-mock-by响应头与自定义response_headers; - 若配置了
delay,通过ngx.sleep延时; - 最终直接返回
response_status与 Body,不再访问上游。
这正是它与proxy-rewrite、response-rewrite等插件的本质区别:mocking 让 APISIX 本身"扮演"后端服务,非常适合后端尚未就绪时的联调场景。
属性详解
插件的完整属性定义(含默认值、取值范围)如下表,对应源码中的 schema 定义:
| 名称 | 类型 | 必选项 | 默认值 | 描述 |
|---|---|---|---|---|
| delay | integer | 否 | 0 | 延时返回的时间,单位为秒;大于 0 时执行ngx.sleep |
| response_status | integer | 否 | 200 | 返回响应的 HTTP 状态码,最小值为 100(minimum = 100) |
| content_type | string | 否 | application/json;charset=utf8 | 返回响应的Content-Type头 |
| response_example | string | 否 | 返回响应的 Body,支持变量(如$remote_addr、$consumer_name),与response_schema二选一 | |
| response_schema | object | 否 | 指定响应的 JSON Schema 对象,仅在未配置response_example时生效 | |
| with_mock_header | boolean | 否 | true | 为true时添加响应头x-mock-by: APISIX/{version} |
| response_headers | object | 否 | 在模拟响应中追加的响应头,键不允许包含冒号:,值支持字符串或数字,如{"X-Foo": "bar"} |
几点来自源码的补充说明:
- 二选一约束:schema 通过
anyOf强制要求response_example与response_schema至少配置其一(见 mocking.lua),否则插件校验不通过。 - Content-Type 白名单:
check_schema会校验content_type(去掉;charset=utf8这类参数后)必须属于application/xml、application/json、text/plain、text/html、text/xml之一(见 mocking.lua 与 mocking.lua),配置其他类型会被拒绝。 - 响应头键约束:
response_headers的键必须匹配^[^:]+$,即不允许包含冒号;值可为 string 或 number。
JSON Schema 随机数据生成原理
response_schema本质是一个 JSON Schema 对象,插件会按字段类型递归生成随机数据。支持的字段类型有:
stringnumberintegerbooleanobjectarray
对应源码中的生成函数(见 mocking.lua):
| 类型 | 生成规则(未提供 example 时) |
|---|---|
| string | 随机生成 1~10 个a~z小写字母 |
| number | math.random() * 10000(0~10000 的浮点数) |
| integer | math.random(1, 10000)(1~10000 的整数) |
| boolean | 随机true/false |
| array | 随机 1~3 个元素,元素按items定义递归生成 |
| object | 遍历properties逐字段递归生成 |
关键规则:每个字段都可以带example值;只要提供了example,该字段就直接返回 example 指定的值,未提供的字段才走随机生成逻辑。因此你可以通过example精确控制部分字段、让其余字段随机化。
以下是一个完整的 JSON 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" }基于该 Schema,插件可能生成的返回对象如下(example字段被原样返回,未设置 example 的字段为随机值):
{ "field1": 123.12, "field3": { "field3_1": "LCFE0", "field3_2": { "field3_2_1": true, "field3_2_2": [ 155, 155 ] } }, "field0": "abcd", "field2": [ "sC" ] }可以看到field0、field1、field3_2_1、field3_2_2中的 155.55(取整为 155)均由example决定,而field3_1的"LCFE0"、field2的"sC"是随机生成的字符串。
Content-Type 与 Body 编码的关系:当content_type为application/xml或text/xml时,生成的随机对象会通过xml2lua.toXml(output, "data")序列化为 XML;当为application/json或text/plain时则用json.encode序列化为 JSON 文本(见 mocking.lua)。
启用插件
通过 Admin API 在指定路由上启用mocking插件。首先从conf/config.yaml中取出admin_key存入环境变量:
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')然后在路由/1上启用插件(以 JSON Schema 方式配置):
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/index.html", "plugins": { "mocking": { "delay": 1, "content_type": "application/json", "response_status": 200, "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 } } }'说明:即使配置了upstream,由于mocking在access阶段直接返回,请求也不会真正转发到127.0.0.1:1980;upstream可以保留(便于后续删除插件后立即恢复真实转发),也可以不配置。
测试插件
以response_example方式配置的示例(状态码 201、开启x-mock-by响应头):
{ "delay":0, "content_type":"", "with_mock_header":true, "response_status":201, "response_example":"{\"a\":1,\"b\":2}" }通过如下命令访问路由(数据面默认监听9080):
curl http://127.0.0.1:9080/test-mock -i返回结果示例:
HTTP/1.1 201 Created Date: Fri, 14 Jan 2022 11:49:34 GMT Content-Type: application/json;charset=utf8 Transfer-Encoding: chunked Connection: keep-alive x-mock-by: APISIX/2.10.0 Server: APISIX/2.10.0 {"a":1,"b":2}注意:Content-Type: application/json;charset=utf8正是源码中content_type的默认值(见 mocking.lua),x-mock-by的值由core.version.VERSION动态拼出(见 mocking.lua)。若将with_mock_header设为false,该响应头将不再出现。
响应头与内置变量支持
response_headers:追加自定义响应头
通过response_headers可向模拟响应追加任意响应头,且值支持 APISIX 内置变量(如$route_id、$remote_addr等),运行时由core.utils.resolve_var解析(见 mocking.lua):
{ "response_example": "hello world", "response_headers": { "X-Apisix": "is, cool", "X-Really": "yes", "X-Route-Id": "$route_id" } }测试 mocking.t 中的 TEST 19~TEST 22 验证了上述行为:X-Apisix、X-Really原样输出,X-Route-Id被解析为当前路由 ID(如1)。
response_example 中的变量
response_example同样支持$变量语法。例如配置"response_example": "remote_addr:$remote_addr",请求后返回remote_addr:127.0.0.1;若变量不存在(如$foo),则被解析为空字符串(对应 mocking.t 的 TEST 15~TEST 18)。变量解析的底层实现位于 apisix/core/utils.lua 的resolve_var:它通过正则(?<!\\)\$(\{(\w+)\}|(\w+))匹配$var或${var},未匹配到的变量返回空串。
删除插件
需要禁用mocking插件时,重新提交不带plugins.mocking的路由配置即可。APISIX 会自动热加载新配置,无需重启服务:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/index.html", "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'删除后,请求将按upstream配置正常转发到真实后端。
测试用例与验证
仓库中的 t/plugin/mocking.t 使用 Test::Nginx 框架对插件做了系统回归验证,覆盖以下行为,可作为理解插件行为的权威参考:
- response_example 固定返回:TEST 1~2 验证
"hello world"原样返回; - Schema 各类型生成:TEST 3~12 分别验证
string(example 生效)、integer、number、boolean、object类型的生成结果与 example 的优先级; - Content-Type 头:TEST 13~14 验证
application/json场景下响应头正确; - 变量解析:TEST 15~18 验证
$remote_addr被解析、未知变量解析为空; - 自定义响应头与内置变量:TEST 19~22 验证
response_headers的静态值与$route_id变量解析。
总结
mocking插件用极低的成本让 APISIX 变成一个"即插即用"的 Mock 服务:response_example适合固定返回的简单场景,response_schema适合需要结构完整、字段随机的复杂响应,delay可用于模拟慢接口,response_headers与内置变量支持则让 Mock 响应更贴近真实后端。结合 插件源码 与 测试用例 阅读,你可以精确掌握每个属性的生效时机,并基于此在测试环境中快速构建可靠的 Mock 服务。
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考