env-manage-plugin
Version:
A dev env plugin that integrates an Express server with request proxying capabilities.
191 lines (190 loc) • 6.88 kB
JavaScript
;
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const express_1 = tslib_1.__importDefault(require("express"));
const http_proxy_middleware_1 = require("http-proxy-middleware");
const set_cookie_parser_1 = tslib_1.__importDefault(require("set-cookie-parser"));
const libCookie = tslib_1.__importStar(require("cookie"));
const Utils_js_1 = tslib_1.__importDefault(require("./Utils.js"));
const Config_js_1 = require("./Config.js");
class PreProxyServer {
static create(envmConfig) {
const { port } = envmConfig;
if (this.appMap[port]) {
console.log(`端口 ${port} 已经启动`);
return null;
}
return new _a(envmConfig);
}
constructor(envmConfig) {
this.app = (0, express_1.default)();
this.envKey = Utils_js_1.default.getRowKey(envmConfig);
this.app.use(this.createPreProxyMiddleware());
this.startServer(envmConfig);
}
getEnvItem() {
const envItem = _a.config.envMap.get(this.envKey);
return envItem;
}
/**
* 当前 代理的 cookie 后缀
*/
get cookieSuffix() {
const envItem = _a.config.envMap.get(this.envKey);
return `-${envItem.port}-${_a.configCookieSuffix}`;
}
/**
* 配置的 cookie 后缀
*/
static get configCookieSuffix() {
return `${_a.config.envmConfig.cookieSuffix}`;
}
/**
* 生成代理中间件
* @returns
*/
createPreProxyMiddleware() {
// 前置转发:将请求转发到 Webpack 开发服务器
return (0, http_proxy_middleware_1.createProxyMiddleware)({
ws: true,
changeOrigin: true,
router: (req) => {
const envItem = _a.config.envMap.get(this.envKey);
const devServerKey = Utils_js_1.default.getRowKey({
name: envItem.devServerName,
});
const devServerConfig = _a.config.devServerMap.get(devServerKey);
// 默认转发到 Webpack 开发服务器
return devServerConfig?.target;
},
on: {
proxyReq: (proxyReq, req) => {
proxyReq.setHeader("X-API-Server", `${req.socket.localPort}`);
this._rewrieCookieOnProxyReq(proxyReq, req);
},
proxyRes: (proxyRes, req, res) => {
this._rewriteSetCookieOnProxyRes(proxyRes);
},
proxyReqWs(proxyReq, req, res) {
proxyReq.setHeader("X-API-Server", `${req.socket.localPort}`);
},
},
});
}
/**
* 代理的时候如果收到了 setcookie 请求
* 给 每一个 setcookie 追加保存一个 代理cookie
* @param proxyRes
*/
_rewriteSetCookieOnProxyRes(proxyRes) {
const envItem = this.getEnvItem();
const setCookie = proxyRes.headers["set-cookie"];
if (envItem.isEnableCookieProxy && setCookie) {
const setCookies = set_cookie_parser_1.default.parse(setCookie);
const proxyCookie = setCookies.map((item) => {
const cookie = {
...item,
name: `${item.name}${this.cookieSuffix}`,
};
return libCookie.serialize(cookie.name, cookie.value, cookie);
});
proxyRes.headers["set-cookie"].push(...proxyCookie);
}
}
/**
* 代理 转发的时候,将对应端口的cookie 重写回去
*/
_rewrieCookieOnProxyReq(proxyReq, req) {
const envItem = this.getEnvItem();
if (envItem.isEnableCookieProxy && req.headers.cookie) {
const cookie = libCookie.parse(req.headers.cookie || "");
const newCookies = [];
Object.keys(cookie).forEach((item) => {
if (item.endsWith(_a.configCookieSuffix)) {
return;
}
let cookieName = `${item}${this.cookieSuffix}`;
if (!cookie[cookieName]) {
cookieName = item;
}
newCookies.push(libCookie.serialize(item, cookie[cookieName]));
});
proxyReq.setHeader("cookie", newCookies.join(";"));
}
}
/**
* 启动服务
* @param envmConfig
* @returns
*/
startServer(envmConfig) {
const { port } = envmConfig;
if (_a.appMap[port]) {
console.log(`端口 ${port} 已经启动`);
return;
}
this.server = this.app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
_a.config.startServer(this.envKey);
});
// 保存所有活动的 socket 连接
this.sockets = new Set();
this.server.on("connection", (socket) => {
this.sockets.add(socket); // 保存 socket
socket.setTimeout(300000); // 设置超时时间为 5 分钟
socket.on("timeout", () => {
socket.destroy();
this.sockets.delete(socket);
});
// 监听 socket 关闭事件
socket.on("close", () => {
this.sockets.delete(socket); // 从集合中移除已关闭的 socket
});
});
_a.appMap[port] = this;
}
static stopServer(port) {
return new Promise((resolve, reject) => {
if (!this.appMap[port]) {
console.log(`端口 ${port} 未启动`);
reject(`端口 【${port}】 未启动`);
return;
}
for (const socket of this.appMap[port].sockets) {
socket.destroy();
}
this.appMap[port].server.close((err) => {
this.config.stopServer(this.appMap[port].envKey);
delete this.appMap[port];
console.log(`Server on port ${port} 已关闭`, err || "");
resolve(1);
});
});
}
/**
* 配置文件变更 检查再配置中已经不存在的环境,并关闭改环境
* @param newConfig
*/
static updateAppMapAfterConfigFileChange() {
const envMap = _a.config.envMap;
Object.entries(_a.appMap).forEach(([port, item]) => {
const rowKey = item.envKey;
if (!envMap.has(rowKey)) {
_a.stopServer(port);
}
});
}
}
_a = PreProxyServer;
/**
* 保存启动的环境实例
*/
PreProxyServer.appMap = {};
PreProxyServer.config = new Config_js_1.Config();
(() => {
_a.config.bus.on(Config_js_1.FILE_CHANGE_EVENT, () => {
_a.updateAppMapAfterConfigFileChange();
});
})();
exports.default = PreProxyServer;