开启代理mock后目标mock不存在将从代理服务器获取数据并创建mock文件
This commit is contained in:
parent
0545b4ffcd
commit
7ded00cfe9
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"routes": {
|
"routes": {
|
||||||
"/api/system/user/info": "mock/service_failed.txt"
|
"/api/system/user/info": "mock/user_info.txt"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"mockEnabled": true,
|
"mockEnabled": true,
|
||||||
|
|||||||
87
index.api.ts
87
index.api.ts
@ -2,6 +2,7 @@ import * as http from "http";
|
|||||||
import * as https from "https";
|
import * as https from "https";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
import * as zlib from "zlib";
|
||||||
|
|
||||||
// 配置文件路径
|
// 配置文件路径
|
||||||
const CONFIG_FILE = path.join(__dirname, "config.json");
|
const CONFIG_FILE = path.join(__dirname, "config.json");
|
||||||
@ -160,6 +161,27 @@ function getMockFilePath(requestPath: string): string {
|
|||||||
return MOCK_ROUTES[requestPath];
|
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) => {
|
const proxyServer = http.createServer((clientReq, clientRes) => {
|
||||||
// 解析客户端请求的 URL
|
// 解析客户端请求的 URL
|
||||||
@ -265,16 +287,75 @@ const proxyServer = http.createServer((clientReq, clientRes) => {
|
|||||||
|
|
||||||
// 检查文件是否存在
|
// 检查文件是否存在
|
||||||
if (!fs.existsSync(mockFilePath)) {
|
if (!fs.existsSync(mockFilePath)) {
|
||||||
console.error(`[MOCK] Mock文件不存在: ${mockFilePath}`);
|
console.warn(`[MOCK] Mock文件不存在,回源并自动生成: ${mockFilePath}`);
|
||||||
clientRes.writeHead(404, { "Content-Type": "application/json" });
|
|
||||||
|
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(
|
clientRes.end(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
error: "Mock file not found",
|
error: "Proxy error",
|
||||||
route: requestPath,
|
route: requestPath,
|
||||||
file: mockFile,
|
file: mockFile,
|
||||||
|
message: err.message,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
clientReq.pipe(proxyReq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
mock/user_info.txt
Normal file
1
mock/user_info.txt
Normal 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"}}}
|
||||||
Loading…
x
Reference in New Issue
Block a user