json-server 常规 Mock 与 Whitelist Proxy 功能开发
本节使用 json-server 构建完整的 Mock 服务,包括基础 CRUD 操作、自定义分页参数、Whitelist 白名单机制和 Proxy 代理转发功能。
项目初始化
# 初始化项目
npm init -y
# 安装 json-server
pnpm install json-server
bash
基础 CRUD 操作
1. 创建数据文件
// db.json
{
"hello": [
{ "id": 1, "message": "hello world" }
]
}
json
2. 配置启动脚本
// package.json
{
"scripts": {
"start": "json-server --watch db.json"
}
}
json
3. RESTful 接口操作
json-server 严格遵循 RESTful 规范:
| 操作 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 查询全部 | GET | /hello | 获取所有数据 |
| 查询单条 | GET | /hello/1 | 获取 ID 为 1 的数据 |
| 新增 | POST | /hello | Body 中传递 JSON 数据 |
| 更新 | PUT | /hello/3 | 路径传 ID,Body 传更新数据 |
| 删除 | DELETE | /hello/8 | 路径传 ID |
新增数据示例(Postman):
POST http://localhost:3000/hello
Content-Type: application/json
{
"message": "hello 1"
}
text
注意:数据需要以数组形式存储才能新增多条记录。ID 为自增字段,即使不传也会自动生成。
更新数据示例:
PUT http://localhost:3000/hello/3
Content-Type: application/json
{
"message": "hello 333"
}
text
更新操作需要路径参数(ID)和 Body 参数两部分配合完成。
新增不存在属性:
json-server 使用文件方式存储,新增的属性也能正常保存:
POST http://localhost:3000/hello
Content-Type: application/json
{
"message": "test",
"name": "新属性"
}
text
自定义分页参数
json-server 默认使用 _page 和 _limit 参数进行分页:
GET http://localhost:3000/hello?_page=1&_limit=2
text
如果项目使用自定义分页参数(如 page 和 size),需要通过自定义中间件实现。
1. 创建 server.js 入口文件
// server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
// 自定义中间件:转换分页参数
server.use((req, res, next) => {
if (req.method === 'GET' && req.query.size && req.query.page) {
const page = parseInt(req.query.page)
const size = parseInt(req.query.size)
req.query._page = page
req.query._limit = size
}
next()
})
server.use(router)
server.listen(3000, () => {
console.log('JSON Server is running')
})
javascript
2. 安装 nodemon 自动重启
pnpm install -D nodemon
bash
// package.json
{
"scripts": {
"dev": "nodemon server.js"
}
}
json
nodemon(Node Monitor)会监听文件变化并自动重启服务。
3. 使用自定义分页
GET http://localhost:3000/hello?page=1&size=2
GET http://localhost:3000/hello?page=2&size=2
text
Whitelist 白名单与 Proxy 代理
Whitelist 的作用:当请求的接口存在于白名单中时,不经过 Mock Server,直接转发到真实服务端。
1. 安装 http-proxy-middleware
pnpm install http-proxy-middleware
bash
2. 配置 URL 重写
使用 json-server 的 rewrite 将所有 API 请求加上前缀:
// server.js 中添加
server.use(jsonServer.rewriter({
'/api/*': '/$1'
}))
javascript
3. 创建 db.json 中的 home 数据
{
"home": [
{ "id": 1, "message": "hello" }
]
}
json
测试 rewrite:GET http://localhost:3000/api/home 可以正常返回数据。
4. 实现 Whitelist + Proxy
// server.js 完整配置
const jsonServer = require('json-server')
const { createProxyMiddleware } = require('http-proxy-middleware')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
// 目标服务器
const testServer = 'http://localhost:3030'
// 白名单配置
const whitelist = router.db.get('whitelist').value()
server.use(middlewares)
// URL 重写
server.use(jsonServer.rewriter({
'/api/*': '/$1'
}))
// Whitelist 中间件
server.use((req, res, next) => {
const isWhitelisted = whitelist.some(item =>
req.method.toLowerCase() === item.method.toLowerCase() &&
req.url.replace('/api/', '') === item.url
)
if (isWhitelisted) {
createProxyMiddleware({
target: testServer,
changeOrigin: true,
pathRewrite: { '^/': '/api/' }
})(req, res, next)
} else {
next()
}
})
// 自定义分页
server.use((req, res, next) => {
if (req.method === 'GET' && req.query.size && req.query.page) {
req.query._page = req.query.page
req.query._limit = req.query.size
}
next()
})
server.use(router)
server.listen(3000, () => {
console.log('JSON Server is running')
})
javascript
5. 在 db.json 中配置 Whitelist
{
"whitelist": [
{ "id": 1, "url": "home", "method": "get" }
],
"hello": [
{ "id": 1, "message": "hello world" }
],
"home": [
{ "id": 1, "message": "from mock server" }
]
}
json
6. 创建第二个 json-server 作为目标服务器
// server1.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db1.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(jsonServer.rewriter({ '/api/*': '/$1' }))
server.use(router)
server.listen(3030, () => {
console.log('JSON Server 1 is running on port 3030')
})
javascript
// db1.json
{
"home": [
{ "id": 1, "message": "from localhost 3030" }
]
}
json
7. 关键问题排查
大小写问题: Express 的 req.method 返回大写(如 GET),需要统一转小写:
req.method.toLowerCase() === item.method.toLowerCase()
javascript
URL 路径问题: rewrite 后 URL 不包含 /api 前缀,但目标服务器需要前缀:
pathRewrite: { '^/': '/api/' } // 为代理请求加回前缀
javascript
通过接口动态管理 Whitelist
Whitelist 数据存储在 db.json 中,可以直接通过 json-server 的 RESTful 接口管理:
# 查看当前白名单
GET http://localhost:3000/whitelist
# 添加白名单规则
POST http://localhost:3000/whitelist
Content-Type: application/json
{
"url": "test",
"method": "get"
}
# 删除白名单规则
DELETE http://localhost:3000/whitelist/2
bash
添加白名单后,对应接口的请求会被代理到真实服务器;删除后则回到 Mock Server 响应。
架构总结
客户端请求
↓
localhost:3000
↓
URL Rewrite (/api/* → /*)
↓
Whitelist 检查
├── 在白名单中 → Proxy 转发到 localhost:3030(真实服务)
└── 不在白名单中 → json-server Mock 响应
↓
自定义分页参数转换
↓
返回响应
text
package.json 完整脚本
{
"scripts": {
"start": "json-server --watch db.json",
"dev": "nodemon server.js",
"dev:server1": "nodemon server1.js"
}
}
json
↑