mock restful接口
mock-restful-api
依赖 express 框架实现的接口 mock 服务,仿照 django-rest-framework 实现。支持列表刷选、模糊搜索、排序,增删改查等操作。
源码 https://github.com/SkylerHu/mock-restful-api

1. 安装
安装
npm install mock-restful-api --save-dev
启动 mock 服务执行 npx mock-restful-api --path <fixtures dir>
全局安装
npm install -g mock-restful-api
启动 mock 服务执行 mock-restful-api --path <fixtures dir>
命令行参数支持
mock-restful-api -h 可查看支持的参数:
shell
Usage: mock-restful-api [options]
Options:
-p, --port <number> mock服务端口,mock service's port number (default: 3001)
--host <string> mock服务监听的IP地址,mock service's IP (default: "0.0.0.0")
--path <string> mock数据文件的路径/目录,mock json file path (default: "fixtures")
--prefix <string> 接口path的前缀,api path prefix (default: "/")
--ignore_watch 忽略监听path参数目录下文件变动而重启服务,ignore watch path for reload app (default: false)
-l --level <string> 日志级别: debug/info/notice/warn/error (default: "debug")
-h, --help display help for command
其中
--path参数定义的目录必须存在,且会自动监听目录下文件变化进而重启 mock 服务。
2. fixtures 配置文件说明
mcok 数据配置示例:users.json
注: + 代表数据格式深度。
| 字段 | 类型 | 说明 | 举例 |
|---|---|---|---|
| restful | string | restful 接口 path 定义 | "web/users/" |
| page_size | integer | list 接口默认分页大小,默认值:20 | 20 |
| filter_fields | object | 定义可以刷选的字段 | {"username": ["exact", "startswith"]} |
| search_fields | array | 定义用于模糊搜索的字段 | ["username"] |
| ordering_fields | array | 定义用于排序的字段 | ["id"] |
| ordering | array | 定义默认排序,+递增(默认); -递减 |
["id"] |
| pk_field | string | 定义数据记录的主键,默认id |
"id" |
| rules | object | 定义 POST 提交数据校验要求 | { "username": { "type":"string" } } |
| rows | array | 定义 mock 数据初始列表数据 | [{...}, {...}] |
| actions | array | 基于 restful 定义的其他操作 | |
| +method | string | 请求方法, GET/POST 等 | |
| +url_path | string | action 路径 | eg: "cancel",则 path 为 /web/users/cancel/ |
| +detail | bool | 是否是详情 action,默认 false | 为 true 时 path 为 /web/users/:pk/cancel/ |
| +response | object | 定义返回值 | { "code": 200,"json": { "message": "success" } } |
| apis | array | 定义其他普通接口 | |
| +path | string | 定义接口 path | |
| +method | string | 请求方法, GET/POST 等 | |
| +response | object | 定义返回值 |
以下按照单个字段配置举例说明.
restful
例如配置 web/users/ 后,基础列表数据用 rows 定义, 服务将支持以下接口:(依赖命令行参数 --prefix="/")
GET /web/users/200获取列表数据- 允许刷选字段由
filter_fields定义 - 模糊搜索,接口使用参数
search,允许模糊搜索的字段由search_fields定义 - 排序接口传递参数
ordering,允许排序的字段由ordering_fields定义
- 允许刷选字段由
POST /web/users/201新建记录, 若配置了rules,将会按照 rules 定义对数据进行校验GET /web/users/:pk([\\w-]+)/200按照pk_field定义主键,根据键值pk获取详情PATCH /web/users/:pk([\\w-]+)/200更新部分数据UPDATE /web/users/:pk([\\w-]+)/200提交完整数据以更新记录DELETE /web/users/:pk([\\w-]+)/204根据主键删除记录
需要注意的是:
- 刷选条件对 详情接口的操作也都生效,先根据 query 参数进行刷选,然后再寻找 pk 的记录
- 新增、修改、删除数据,会实际对
rows数据操作生效,mock 服务重启后数据重置; - 若是启动 mock 服务的参数
--prefix=openapi则生成接口示例为GET /openapi/web/users/
filter_fields
对列表数据刷选,能够筛选的字段必须在该字段中明确定义,示例如下:
json
{
"filter_fields": {
"id": ["exact", "in"],
"username": ["exact", "in", "contains", "startswith", "endswith", "regex"],
"age": ["exact", "range", "lt", "lte", "gt", "gte", "isnull"],
"created_at": ["range"],
"city__name": ["exact", "in"]
}
}
其中 field 作为配置数据的键, lookup 作为值,定义筛选的字段。
- 基本的查找关键字参数采用形式
field__lookup=value(使用双下划线)exact完全匹配,实现的是==运算;eg:username=skyler等价于username__exact=skylerisnull刷选数据是否为空的记录age__isnull=1筛选数据为undefined/null的数据,值为""不符合条件age__isnull=0熟宣数据不为空的数据
in参数是列表值,可用英文逗号,隔开;eg:id__in=1,2,3,返回 username 值在[1,2,3]内的数据startswith前缀匹配,eg:username__startswith=skyendswith后缀匹配,eg:username__endswith=lercontains字符串包含,eg:username__contains=kyregex字符串正则, eg:username__regex=sk.*lerrange区间范围,用于日期、数字甚至字符,传递 2 个值时使用逗号,隔开age__range=1,100刷选 age 值在 [1,100] 内的记录,即0 <= age <= 100age__range=1筛选age >= 1的记录,等价于age__gte=100age__range=,100筛选age <= 100的记录,等价于age__lte=100
lt小于, eg:age__lt=100刷选age < 100的记录lte小于等于, eg:age__lte=100刷选age <= 100的记录gt大于, eg:age__gt=1刷选age > 1的记录gte大于等于, eg:age__gte=1刷选age >= 1的记录
- 若是 query 参数中对应值为空字符串,则查询条件不生效;例如
username=&search=这两个条件都是无效刷选; - 可用
__(使用双下划线)定义多级深度的数据查找; eg:city__name__in="beijing"可帅选出以下数据
json
[
{
"id": 1,
"username": "admin",
"city": {
"name": "beijing"
}
}
]
search_fields
定义模糊搜索的字段,示例:
json
{
"search_fields": ["username", "nickname", "city__name"]
}
通过 query 传递参数 search=sky 从 rows 记录中按照字段 username / nickname / city.name 判断是否包含 sky 的记录,其中任意一个字段匹配成功即符合条件。
ordering_fields
定义可以用于排序的字段,示例:
json
{
"ordering_fields": ["id", "name"],
"ordering": ["id"]
}
通过 query 传递参数 ordering=-id,+name ,表示返回的列表数据 按照 id 降序 且 name 升序 的顺序返回。
若 query 没有传递 ordering 参数,则按照默认的配置 "ordering": ["id"] 对 id 升序 返回数据,无符号 +/-时默认为 +升序。
pk_field
定义 rows 列表数据的主键,默认为 id。详情接口中 <pk> 值与该字段值匹配。
请求 GET /web/users/1/ 则是返回 rows 中数据 id=1 的记录。
rules
定义 新增/修改 数据的校验规则,示例:
json
{
"rules": {
"username": { "type": "string", "pattern": "\\w+", "required": true },
"is_active": { "type": "boolean" },
"age": { "type": "number", "integer": true, "min": 0, "max": 100 },
"gender": { "type": "string", "valid": ["male", "female"] }
}
}
username字符串正则,且是必须的字段is_active定义 bool 类型age数值定义取值范围gender字符串,valid 定义枚举值范围
校验规则通过 joi 实现,将 json 配置转成成 Joi 的校验类。具体支持的类型和方法参照 https://joi.dev/api/
actions
actions 是对 restful 的扩展,依赖 restful 的定义,示例:
json
{
"actions": [
{
"method": "POST",
"url_path": "create/",
"response": {}
},
{
"method": "get",
"url_path": "releated/",
"detail": true,
"response": {}
}
]
}
以上配置根据拼接规则 {restful}/{url_path} 会生成以下接口:
POST /web/users/create/GET /web/users/:pk([\\w-]+)/releated/因为定义了detail=true,所以路由支持传递pk- 需要注意的是,
pk只要符合正则定义,无论何值,返回结果都按照response定义返回 - 即
GET /web/users/1/releated/和/web/users/2/releated/返回值一样
- 需要注意的是,
注意:生成的接口 path 是否
/结尾,取决于restful的配置是否/结尾。
apis
定义其他扩展的接口,不依赖 restful ,可单独存在,示例:
json
{
"apis": [
{
"method": "get",
"path": "web/enums/",
"response": {
"code": 200,
"text": "text"
}
}
]
}
response 返回值配置
actions 和 apis 中的配置格式一样,接口都按照配置的数据返回结果。
| 字段 | 类型 | 说明 | 举例 |
|---|---|---|---|
| code | intrger | 定义返回状态码 | 默认值 200 |
| headers | object | 定义返回 Header 键值对 | {"Content-Type": "image/png"} |
| json | any | 定义返回的 json 数据 | |
| text | string | 定义返回的文本数据 | |
| file | string | 定义实现下载文件 | 配置文件相对(当前运行路径)/绝对路径, eg: ./test.jpg |
3. 接口请求示例
列表接口
shell
curl "http://0.0.0.0:3001/web/users/?is_active=1&ordering=-id&city__name=anhui&search=sky"
返回状态码为 200:
json
{
"count": 1,
"results": [
{
"id": 2,
"username": "skyler",
"nickname": "Skyler",
"is_active": true,
"age": 18,
"gender": "male",
"score": 99.9,
"created_at": "2024-08-19 21:33:26",
"groups": [
{
"id": "2",
"name": "dev"
}
],
"city": {
"id": 2,
"name": "anhui"
}
}
]
}
创建记录
shell
curl -XPOST "http://0.0.0.0:3001/web/users/" -H "Content-Type: application/json" -d '{"username":"test"}'
返回状态码为 201:
json
{
"id": 6,
"username": "test"
}
修改接口
shell
curl -XPATCH "http://0.0.0.0:3001/web/users/6/" -H "Content-Type: application/json" -d '{"username":"test2"}'
返回状态码为 200:
json
{
"id": 6,
"username": "test2"
}
详情接口
shell
curl "http://0.0.0.0:3001/web/users/6/"
返回状态码为 200:
json
{
"id": 6,
"username": "test2"
}
删除接口
shell
curl -XDELETE "http://0.0.0.0:3001/web/users/6/"
返回状态码为 204,无返回值。
4. 项目中配置接口 Proxy
以 React 项目为例,在 src/setupProxy.js 文件中增加如下配置:
javascript
const createProxyMiddleware = require("http-proxy-middleware");
module.exports = function (app) {
if (process.env.NODE_ENV !== "production") {
app.use(
createProxyMiddleware("/web/users", {
target: "http://0.0.0.0:3001",
changeOrigin: true,
logLevel: "debug",
})
);
}
};
proxy 更多配置参考 http-proxy-middleware