fix: 修复 YAML 块语法 body 匹配失败问题

- normalize_yaml_body 函数在解析 JSON 前添加 trim() 处理,解决 YAML `|` 和 `>` 语法产生的前导空格问题
- 修复 multiple_login.yaml 中 response body 格式错误(YAML 对象改为 JSON 字符串)
This commit is contained in:
2026-03-27 17:33:21 +08:00
parent 9c1d0e16b4
commit 061ceff4b8
27 changed files with 1439 additions and 415 deletions

View File

@@ -1,28 +0,0 @@
id: "auth_login_001"
request:
method: "POST"
path: "/api/v1/auth/login"
# 必须包含此 Header 才会匹配
headers:
Content-Type: "application/json"
Authorization: "111"
host: "127.0.0.1:8080"
body: >
{
"username":"user",
"password":"123"
}
response:
status: 200
headers:
Content-Type: "application/json"
X-Mock-Engine: "Rust-Gemini-v1.2"
# 直接内联 JSON 字符串
body: >
{
"code": 0,
"data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6" },
"msg": "success"
}
settings:
delay_ms: 2000 # 模拟真实网络延迟

View File

@@ -1,50 +0,0 @@
- id: "auth_login_out_001"
request:
method: "POST"
path: "/api/v1/auth/login_out"
# 必须包含此 Header 才会匹配
headers:
Content-Type: "application/json"
Authorization: "111"
host: "127.0.0.1:8080"
body:
type: true
response:
status: 200
headers:
Content-Type: "application/json"
X-Mock-Engine: "Rust-Gemini-v1.2"
# 直接内联 JSON 字符串
body: >
{
"code": 0,
"data": "退出成功",
"msg": "success"
}
settings:
delay_ms: 200 # 模拟真实网络延迟
- id: "auth_login_out_002"
request:
method: "POST"
path: "/api/v1/auth/login_out"
# 必须包含此 Header 才会匹配
headers:
Content-Type: "application/json"
Authorization: "111"
host: "127.0.0.1:8080"
body:
type: false
response:
status: 200
headers:
Content-Type: "application/json"
X-Mock-Engine: "Rust-Gemini-v1.2"
# 直接内联 JSON 字符串
body: >
{
"code": 1,
"data": "退出失败",
"msg": "success"
}
settings:
delay_ms: 200 # 模拟真实网络延迟

View File

@@ -0,0 +1,118 @@
# 用户登录 - JSON 格式
- name: "user_login_002"
request:
path: "/v1/auth/login"
method: "POST"
headers:
Content-Type: "application/json"
Authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6"
host: "127.0.0.1:8080"
body: >
{
"username": "user002",
"password": "password123"
}
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6",
"userId": 10002,
"username": "user002",
"role": "administrator"
}
}
settings:
delay_ms: 2000 # 模拟真实网络延迟
- name: "user_login_003"
request:
path: "/v1/auth/login"
method: "POST"
headers:
Content-Type: "application/json"
Authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6"
host: "127.0.0.1:8080"
body: |
{
"username": "user003",
"password": "password123"
}
response:
status: 200
headers:
Content-Type: "application/json"
body: >
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6",
"userId": 10003,
"username": "user003",
"role": "administrator"
}
}
settings:
delay_ms: 2000 # 模拟真实网络延迟
- name: "user_login_004"
request:
path: "/v1/auth/login"
method: "POST"
headers:
Content-Type: "application/json"
Authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6"
host: "127.0.0.1:8080"
body: |
{
"username": "user004",
"password": "password123"
}
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6",
"userId": 10004,
"username": "user004",
"role": "administrator"
}
}
- name: "user_login_005"
request:
path: "/v1/auth/login"
method: "POST"
headers:
Content-Type: "application/json"
Authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6"
host: "127.0.0.1:8080"
body:
username: "user005"
password: "password123"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6",
"userId": 10005,
"username": "user005",
"role": "administrator"
}
}

View File

@@ -0,0 +1,26 @@
# 用户注册 - JSON 格式
name: "user_register"
request:
method: "POST"
path: "/v1/auth/register"
headers:
Content-Type: "application/json"
body:
username: "newuser"
password: "newpass123"
email: "newuser@example.com"
response:
status: 201
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "注册成功",
"data": {
"userId": 10002,
"username": "newuser",
"email": "newuser@example.com",
"createdAt": "2026-03-27T10:00:00Z"
}
}

View File

@@ -0,0 +1,29 @@
# 用户登录 - JSON 格式
name: "user_login_001"
request:
path: "/v1/auth/login"
method: "POST"
headers:
Content-Type: "application/json"
Authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6"
host: "127.0.0.1:8080"
body:
username: "user001"
password: "password123"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6",
"userId": 10001,
"username": "user001",
"role": "administrator"
}
}
settings:
delay_ms: 2000 # 模拟真实网络延迟

30
mocks/v1/data/export.yaml Normal file
View File

@@ -0,0 +1,30 @@
# XML 数据导出 - XML 格式
name: "data_export"
request:
method: "POST"
path: "/v1/data/export"
headers:
Content-Type: "application/xml"
body: |
<?xml version="1.0" encoding="UTF-8"?>
<request>
<userId>10001</userId>
<format>xml</format>
</request>
response:
status: 200
headers:
Content-Type: "application/xml"
body: |
<?xml version="1.0" encoding="UTF-8"?>
<response>
<code>0</code>
<message>导出成功</message>
<data>
<user>
<id>10001</id>
<name>管理员</name>
<email>admin@example.com</email>
</user>
</data>
</response>

15
mocks/v1/health.yaml Normal file
View File

@@ -0,0 +1,15 @@
# 健康检查 - GET 无 Body
name: "health_check"
request:
method: "GET"
path: "/v1/health"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"status": "healthy",
"version": "2.0.0",
"timestamp": "2026-03-27T10:00:00Z"
}

View File

@@ -1,12 +1,12 @@
id: "prod_export_pdf"
name: "prod_export_pdf"
request:
method: "GET"
path: "/api/v1/products/report"
body: '{"username":"user","password":"123"}'
path: "/v1/products/report"
body: '{"username":"user001","password":"password123"}'
response:
status: 200
headers:
Content-Type: "application/pdf"
Content-Disposition: "attachment; filename=report.pdf"
# 智能协议:引擎会自动识别前缀并异步读取磁盘文件
body: "file://./storage/reports/annual_2024.pdf"
body: "file://./storage/v1/hello.pdf"

View File

@@ -1,16 +0,0 @@
# 使用 YAML 数组语法定义多个规则
- id: "sys_ping"
request:
method: "GET"
path: "/api/v1/ping"
response:
status: 200
body: "pong"
- id: "sys_version"
request:
method: "GET"
path: "/api/v1/version"
response:
status: 200
body: '{"version": "1.2.0-smart"}'

View File

@@ -1,23 +0,0 @@
id: "upload_file"
request:
method: "POST"
path: "/api/v1/upload"
headers:
Content-Type: "multipart/form-data"
response:
status: 200
headers:
Content-Type: "application/json"
body: >
{
"code": 0,
"data": {
"filename": "example.txt",
"path": "storage/2024-01-15/example.txt",
"size": 1024,
"url": "/storage/2024-01-15/example.txt"
},
"msg": "upload success"
}
settings:
delay_ms: 100

73
mocks/v1/user/avatar.yaml Normal file
View File

@@ -0,0 +1,73 @@
# 上传头像 - Multipart 格式(数组形式,只匹配字段名)
- name: "user_upload_avatar_001"
request:
method: "POST"
path: "/v1/user/avatar"
headers:
Content-Type: "multipart/form-data"
body:
- "avatar1"
- "description1"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "头像上传成功",
"data": {
"url": "https://cdn.example.com/v1/avatars/10001.jpg",
"size": 204800,
"filename": "avatar.jpg"
}
}
- name: "user_upload_avatar_002"
request:
method: "POST"
path: "/v1/user/avatar"
headers:
Content-Type: "multipart/form-data"
body:
avatar2: "avatar"
description2: "description"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "头像上传成功",
"data": {
"url": "https://cdn.example.com/v1/avatars/10002.jpg",
"size": 204800,
"filename": "avatar.jpg"
}
}
- name: "user_upload_avatar_003"
request:
method: "POST"
path: "/v1/user/avatar"
headers:
Content-Type: "multipart/form-data"
body: >
{
"avatar3": "avatar"
"description3": "description"
}
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "头像上传成功",
"data": {
"url": "https://cdn.example.com/v1/avatars/10003.jpg",
"size": 204800,
"filename": "avatar.jpg"
}
}

View File

@@ -0,0 +1,13 @@
# 下载用户数据文件 - file:// 协议
name: "user_download"
request:
method: "GET"
path: "/v1/user/download"
query_params:
format: "json"
response:
status: 200
headers:
Content-Type: "application/octet-stream"
Content-Disposition: "attachment; filename=user_data.json"
body: "file://./storage/v1/user_data.json"

13
mocks/v1/user/echo.yaml Normal file
View File

@@ -0,0 +1,13 @@
# 文本回显 - Text 格式
name: "user_echo"
request:
method: "POST"
path: "/v1/user/echo"
headers:
Content-Type: "text/plain"
body: "Hello V1 Mock Server"
response:
status: 200
headers:
Content-Type: "text/plain"
body: "Echo from V1: Hello V1 Mock Server"

View File

@@ -0,0 +1,24 @@
# 表单登录 - Form 格式
name: "_user_login_form"
request:
method: "POST"
path: "/v1/user/login/form"
headers:
Content-Type: "application/x-www-form-urlencoded"
body:
username: "formuser"
password: "formpass"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "表单登录成功",
"data": {
"token": "v2_form_token_xyz",
"userId": 20001,
"username": "formuser"
}
}

View File

@@ -0,0 +1,24 @@
# 获取用户信息 - GET 无 Body需要 Authorization Header
name: "user_profile"
request:
method: "GET"
path: "/v1/user/profile"
headers:
Authorization: "Bearer v1_test_token"
response:
status: 200
headers:
Content-Type: "application/json"
body: |
{
"code": 0,
"message": "获取成功",
"data": {
"userId": 10001,
"username": "admin",
"email": "admin@example.com",
"nickname": "管理员",
"avatar": "https://example.com/avatars/admin.jpg",
"createdAt": "2025-01-01T00:00:00Z"
}
}

View File

@@ -1,11 +0,0 @@
id: "user_search_admin"
request:
method: "GET"
path: "/api/v1/users"
# 请求中必须包含 role=admin 且 status=active
query_params:
role: "admin"
status: "active"
response:
status: 200
body: '{"users": [{"id": 1, "name": "SuperAdmin"}]}'