const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const fs = require('fs');
const JSONStream = require('JSONStream');
const app = express();
const port = 10086;
const targetUrl = 'https://lgkp-uat.ihanchen.com/';
const tartUrlKey = 'lgkp-uat';
const MOCK = false;
const MOCK_FAIL_DEFAULT = {
code: -1,
msg: '接口调用失败',
success: false,
}
const ignoreParamKey = ['code', 'phoneCode', 'third_id', 'clickId', 'startTime', 'endTime']
function readFileStreamAsync(filePath, apiKey) {
return new Promise((resolve, reject) => {
const fileReadStream = fs.createReadStream(filePath);
const parser = JSONStream.parse("0.data");
fileReadStream.pipe(parser)
parser.on('data', data => {
// console.log('fileReadStream', data);
if (data[apiKey]) {
resolve(data[apiKey])
} else {
reject(undefined)
}
})
parser.on('error', err => {
console.log(err)
reject(err)
})
})
}
function getBodyFromReq(req) {
return new Promise((resolve, reject) => {
if (req.method === 'POST' || req.method === 'PUT') {
let bodyData = '';
req.on('data', chunk => {
bodyData += chunk.toString();
});
req.on('end', () => {
// console.log('Body data:', bodyData); // 字符串类型
resolve(bodyData)
});
} else {
resolve('{}');
}
});
}
function getBodyFromRes(proxyRes) {
return new Promise((resolve, reject) => {
console.log('getBodyFromRes init');
let bodyData = [];
proxyRes.on('data', chunk => {
// console.log('on data', Buffer.concat([chunk]).toString());
bodyData.push(chunk);
});
proxyRes.on('end', () => {
bodyData = Buffer.concat(bodyData).toString();
// console.log('on end:', bodyData); // 字符串类型
try {
const body = JSON.parse(bodyData)
resolve(body);
} catch (e) {
console.log('出错了啊')
reject(e)
}
});
});
}
app.use('/', createProxyMiddleware({
target: targetUrl,
changeOrigin: true,
on: {
proxyReq: async (proxyReq, req, res) => {
/* handle proxyReq */
// console.log('proxyReq, req, res', {proxyReq, req, res})
let reqBody = await getBodyFromReq(req);
// console.log('delete ignoreParamKey before', reqBody);
if (ignoreParamKey && ignoreParamKey.length) {
const reqBodyObj = JSON.parse(reqBody);
for(let key in reqBodyObj) {
if (ignoreParamKey.includes(key)) {
delete reqBodyObj[key];
}
}
reqBody = JSON.stringify(reqBodyObj);
}
// console.log('delete ignoreParamKey after', reqBody);
req.reqBody = reqBody;
const { method, path, params, query } = req;
if (ignoreParamKey && ignoreParamKey.length) {
for(let key in params) {
if (ignoreParamKey.includes(key)) {
delete params[key];
}
}
}
const fileName = `${JSON.stringify(params)} ${JSON.stringify(query)} ${reqBody.slice(0, 50)}`;
const apiKey = `${JSON.stringify(params)} ${JSON.stringify(query)} ${reqBody}`;
const dirPath = `./src/buffers/${tartUrlKey}/${method}/${encodeURIComponent(path)}`;
const filePath = `${dirPath}/${encodeURIComponent(fileName)}.json`;
if (!fs.existsSync(`./src/buffers/${tartUrlKey}`)) {
fs.mkdirSync(`./src/buffers/${tartUrlKey}`);
}
if (!fs.existsSync(`./src/buffers/${tartUrlKey}/${method}`)) {
fs.mkdirSync(`./src/buffers/${tartUrlKey}/${method}`);
}
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, JSON.stringify([{data: {}}]))
}
if (MOCK) {
try {
const dataMock = await readFileStreamAsync(filePath, apiKey);
// 解析原始响应体
let parsedData = dataMock;
// 设置新的响应头并发送修改后的数据
// res.setHeader('Content-Length', JSON.stringify(parsedData).length);
res.json(parsedData);
} catch (e) {
console.trace(e);
res.json(MOCK_FAIL_DEFAULT);
// res.end("my response to cli");
}
}
},
proxyRes: async (proxyRes, req, res) => {
/* handle proxyRes */
// console.log('proxyRes, req, res', {proxyRes, req, res})
if (!MOCK) {
try {
const reqBody = req.reqBody || '{}';
// console.log('reqBody:', reqBody);
const { method, path, params, query } = req;
if (ignoreParamKey && ignoreParamKey.length) {
for(let key in params) {
if (ignoreParamKey.includes(key)) {
delete params[key];
}
}
}
// console.log('params, query', {params, query});
const fileName = `${JSON.stringify(params)} ${JSON.stringify(query)} ${reqBody.slice(0, 50)}`;
const apiKey = `${JSON.stringify(params)} ${JSON.stringify(query)} ${reqBody}`;
const dirPath = `./src/buffers/${tartUrlKey}/${method}/${encodeURIComponent(path)}`;
const filePath = `${dirPath}/${encodeURIComponent(fileName)}.json`;
// console.log('开始解析返回数据' + path);
let respBody = await getBodyFromRes(proxyRes).catch(e => {
console.trace(e);
});
// console.log('结束解析返回数据: ' + respBody);
if (respBody && respBody.success) {
// console.log("res body from proxied server:", body);
const fileWriteStream = fs.createWriteStream(filePath);
const stringify = JSONStream.stringify();
stringify.pipe(fileWriteStream);
const data = {};
data[apiKey] = respBody;
stringify.write({
data,
});
stringify.end();
}
res.end("my response to cli");
} catch(e) {
console.trace(e);
console.log("err req from proxied server:", {
method, path, params, query
});
}
}
},
error: (err, req, res) => {
/* handle error */
},
},
}));
app.listen(port, () => {
console.log(`Proxy server is running on port ${port}`);
});