开启代理mock后目标mock不存在将从代理服务器获取数据并创建mock文件

This commit is contained in:
tony 2026-04-10 16:56:25 +08:00
parent 0545b4ffcd
commit 7ded00cfe9
3 changed files with 93 additions and 11 deletions

View File

@ -1,6 +1,6 @@
{
"routes": {
"/api/system/user/info": "mock/service_failed.txt"
"/api/system/user/info": "mock/user_info.txt"
},
"config": {
"mockEnabled": true,

View File

@ -2,6 +2,7 @@ import * as http from "http";
import * as https from "https";
import * as fs from "fs";
import * as path from "path";
import * as zlib from "zlib";
// 配置文件路径
const CONFIG_FILE = path.join(__dirname, "config.json");
@ -160,6 +161,27 @@ function getMockFilePath(requestPath: string): string {
return MOCK_ROUTES[requestPath];
}
function decodeBodyByEncoding(
bodyBuffer: Buffer,
contentEncoding?: string,
): Buffer {
const encoding = (contentEncoding || "").toLowerCase().trim();
try {
if (encoding.includes("gzip")) {
return zlib.gunzipSync(bodyBuffer);
}
if (encoding.includes("br")) {
return zlib.brotliDecompressSync(bodyBuffer);
}
if (encoding.includes("deflate")) {
return zlib.inflateSync(bodyBuffer);
}
} catch (error) {
console.warn("[MOCK] 解压上游响应失败,按原始内容写入文件", error);
}
return bodyBuffer;
}
// 代理服务器
const proxyServer = http.createServer((clientReq, clientRes) => {
// 解析客户端请求的 URL
@ -265,16 +287,75 @@ const proxyServer = http.createServer((clientReq, clientRes) => {
// 检查文件是否存在
if (!fs.existsSync(mockFilePath)) {
console.error(`[MOCK] Mock文件不存在: ${mockFilePath}`);
clientRes.writeHead(404, { "Content-Type": "application/json" });
console.warn(`[MOCK] Mock文件不存在回源并自动生成: ${mockFilePath}`);
const targetPort = CONFIG.targetPort ?? 443;
const options: http.RequestOptions = {
hostname: CONFIG.targetHost,
port: targetPort,
method: clientReq.method,
path: parsedUrl.pathname + parsedUrl.search,
headers: {
...clientReq.headers,
host: CONFIG.targetHost,
},
};
const proxyReq = https.request(options, (proxyRes) => {
const chunks: Buffer[] = [];
proxyRes.on("data", (chunk: Buffer) => {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
});
proxyRes.on("end", () => {
const bodyBuffer = Buffer.concat(chunks);
try {
const decodedBuffer = decodeBodyByEncoding(
bodyBuffer,
Array.isArray(proxyRes.headers["content-encoding"])
? proxyRes.headers["content-encoding"][0]
: proxyRes.headers["content-encoding"],
);
const contentType = String(proxyRes.headers["content-type"] || "");
const toWrite =
contentType.includes("application/json") ||
contentType.includes("text/") ||
contentType.includes("application/xml") ||
contentType.includes("application/javascript")
? decodedBuffer.toString("utf-8")
: decodedBuffer;
fs.mkdirSync(path.dirname(mockFilePath), { recursive: true });
fs.writeFileSync(mockFilePath, toWrite);
console.log(`[MOCK] 已自动写入mock文件: ${mockFilePath}`);
} catch (writeErr) {
console.error(`[MOCK] 自动写入mock文件失败: ${mockFilePath}`, writeErr);
}
clientRes.writeHead(proxyRes.statusCode || 200, {
...proxyRes.headers,
"X-Mock-Autogenerated": "true",
"X-Mock-Source": mockFile,
});
clientRes.end(bodyBuffer);
});
});
proxyReq.on("error", (err) => {
console.error("Proxy request error:", err);
clientRes.writeHead(500, { "Content-Type": "application/json" });
clientRes.end(
JSON.stringify({
error: "Mock file not found",
error: "Proxy error",
route: requestPath,
file: mockFile,
message: err.message,
timestamp: new Date().toISOString(),
}),
);
});
clientReq.pipe(proxyReq);
return;
}

1
mock/user_info.txt Normal file
View File

@ -0,0 +1 @@
{"code":200,"msg":"","data":{"permissions":["quant:account:create","quant:strategy:create","quant:alarm:create","quant:agentServer:create","quant:form:create","quant:robotPosition:create","quant:robot:create","quant:robotOrder:create","quant:robotOrder:delete","quant:account:delete","quant:strategy:delete","quant:robot:delete","quant:agentServer:delete","quant:robotPosition:delete","quant:alarm:delete","quant:form:delete","quant:agentServer:update","quant:robotOrder:update","quant:robotPosition:update","quant:robot:update","quant:alarm:update","quant:account:update","system:file:upload","quant:strategy:update","quant:form:update","quant:robot:select","quant:agentServer:select","quant:account:select","system:file:delete","quant:strategy:select","quant:robotOrder:select","quant:robotPosition:select","quant:alarm:select","quant:form:select","quant:strategy:transfer","quant:robot:deploy","quant:form:design","system:file:select","quant:robot:run","system:file:category","quant:robot:notify"],"roles":["quant_vip"],"user":{"userId":1933359028013174785,"parentId":0,"inviteCode":"QfWk5SDx","username":"h01LxpmZfGzWu8dv5xdh","avatar":"","nickname":"Sandy","phone":"","birthday":"2025-07-07","email":"975303544@qq.com","sex":2,"deptId":null,"deptName":null,"postId":null,"postName":null,"creditScore":100,"score":0,"wallet":0.00,"registerDate":"2025-06-13 11:01:27"}}}