f2e-server3
Version:
f2e-server 3.0
177 lines (176 loc) • 8.51 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const engine_1 = require("../../utils/engine");
const http = __importStar(require("node:http"));
const https = __importStar(require("node:https"));
const renderItem_1 = require("./renderItem");
const resp_1 = require("../../utils/resp");
const utils_1 = require("../../utils");
const fs = __importStar(require("node:fs"));
const path = __importStar(require("node:path"));
const middleware_proxy = {
name: 'proxy',
mode: ['dev', 'prod'],
execute: (conf) => {
const { proxies = [] } = conf;
if (proxies.length === 0) {
return;
}
const items = proxies.map(renderItem_1.renderItem);
return {
beforeRoute(pathname, ctx) {
const { req, resp } = ctx;
const url = req.getUrl();
const search = req.getQuery();
const item = items.find(item => {
return item.match(url, ctx);
});
if (!item) {
return;
}
const origin = item.getOrigin(url, ctx);
const { timeout = 5000, requestOptions = {}, requestHeaders = h => h, responseHeaders = h => h, responseRender = h => h, } = item;
const newPath = new URL(typeof item.pathname === 'function'
? url.replace(item.location, item.pathname)
: url.replace(item.location, item.pathname || (typeof item.location === 'string' ? item.location : '')), origin);
if (search) {
newPath.search = search;
}
const isStream = item.stream || false;
const saver = item.saver;
const _pathname = saver?.pathFixer ? saver.pathFixer(pathname, ctx) : pathname;
const dataPath = saver?.pathBodyDir ? path.join(saver.pathBodyDir, _pathname) : null;
if (saver && dataPath) {
if (!fs.existsSync(saver.pathBodyDir)) {
fs.mkdirSync(saver.pathBodyDir, { recursive: true });
}
if (!fs.existsSync(saver.pathHeaders)) {
fs.mkdirSync(path.dirname(saver.pathHeaders), { recursive: true });
fs.writeFileSync(saver.pathHeaders, JSON.stringify({}));
}
const proxyHeadersMap = JSON.parse(fs.readFileSync(saver.pathHeaders, 'utf-8'));
if (fs.existsSync(dataPath)) {
const stats = fs.statSync(dataPath);
if (stats.isFile()) {
resp.cork(() => {
resp.writeStatus('200 OK');
(0, resp_1.commonWriteHeaders)(resp, proxyHeadersMap[_pathname] || {});
resp.write(fs.readFileSync(dataPath));
resp.end();
});
return false;
}
}
}
try {
const creq = (/^https/i.test(newPath.protocol) ? https : http).request(newPath, {
method: req.getMethod(),
headers: {
...requestHeaders((0, resp_1.getHttpHeaders)(req), ctx),
host: newPath.host,
},
timeout: isStream ? 86400000 : timeout,
...requestOptions,
}, function (res) {
resp.cork(() => {
resp.writeStatus(res.statusCode + ' ' + res.statusMessage);
(0, resp_1.commonWriteHeaders)(resp, responseHeaders((0, resp_1.getHttpHeaders)(res), res, ctx));
});
const chunks = [];
res
.on('data', function (data) {
if (isStream) {
resp.cork(() => {
resp.write(data);
});
}
else {
chunks.push(data);
}
}).on('end', function () {
if (isStream) {
resp.end();
return;
}
const result = responseRender(Buffer.concat(chunks), res, ctx);
const headers = responseHeaders((0, resp_1.getHttpHeaders)(res), res, ctx);
if (saver && dataPath) {
const proxyHeadersMap = JSON.parse(fs.readFileSync(saver.pathHeaders, 'utf-8'));
proxyHeadersMap[_pathname] = headers;
fs.writeFileSync(saver.pathHeaders, JSON.stringify(proxyHeadersMap, null, 2));
if (!fs.existsSync(dataPath)) {
fs.mkdirSync(path.dirname(dataPath), { recursive: true });
fs.writeFileSync(dataPath, result);
}
else if (!fs.statSync(dataPath).isDirectory()) {
fs.writeFileSync(dataPath, result);
}
}
resp.cork(() => {
resp.write(result);
resp.end();
});
});
}).on('timeout', function () {
resp.cork(() => {
resp.writeStatus('504 Gateway Timeout');
(0, resp_1.commonWriteHeaders)(resp, {});
resp.end('504 Gateway Timeout');
});
}).on('error', function (err) {
utils_1.logger.error(`[proxy error]`, newPath, err);
});
switch (engine_1.ENGINE_TYPE) {
case "node":
case "bun":
case "deno":
req.request.pipe(creq);
break;
case "uws":
resp.onData(function (data, finished) {
data && data.byteLength > 0 && creq.write((0, utils_1.toBuffer)(data));
if (finished) {
creq.end();
}
});
resp.onAborted(() => {
creq.destroy();
});
}
}
catch (e) {
resp.cork(() => {
resp.writeStatus('502 Bad Gateway');
(0, resp_1.commonWriteHeaders)(resp, {});
resp.end(e + '');
});
}
return false;
},
};
}
};
exports.default = middleware_proxy;