@cliz/inlets
Version:
Cloud Native Tunnel
100 lines (99 loc) • 3.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const doreamon_1 = require("@zodash/doreamon");
const utils_1 = require("../../../utils");
const debug = require('debug')('inlets:tunnel:tcp');
const logger = doreamon_1.default.logger.getLogger('tunnel:http');
function createServer(ctx, options) {
const domain = options.domain;
const subDomainRe = new RegExp(`([^.]+).${domain}`);
let requestCount = 0;
const attach = (server) => {
server.on('connection', (tcpSocket) => {
const socketConfig = {
tcpId: doreamon_1.default.uuid(),
domain: null,
subDomain: null,
isWs: false,
};
const request = async (tcpId, data, callback) => {
var _a;
requestCount += 1;
if (socketConfig.isWs) {
return;
}
if (!socketConfig.domain) {
const req = new utils_1.Request(data);
socketConfig.domain = req.get('host');
socketConfig.req = req;
if (req.path === ctx.config.wsPath) {
socketConfig.isWs = true;
return;
}
if (socketConfig.domain) {
const matched = socketConfig.domain.match(subDomainRe);
if (matched) {
socketConfig.subDomain = matched[1];
}
}
}
const requestLog = `[${socketConfig.subDomain}.${domain}][request: ${requestCount}] ${(_a = socketConfig.req) === null || _a === void 0 ? void 0 : _a.getRequestLog()}`;
if (!socketConfig.subDomain) {
logger.info(`[404]${requestLog}`);
return destroy(tcpSocket);
}
const wt = ctx.domainMappings.get(socketConfig.subDomain);
let domainSocket = null;
if (!!wt) {
domainSocket = wt.wsSocket;
wt.tcpSocket = tcpSocket;
}
debug('mapping:', socketConfig.domain, socketConfig.subDomain, !!domainSocket);
if (!domainSocket) {
logger.info(`[404]${requestLog}`);
return destroy(tcpSocket);
}
logger.info(requestLog);
const requestId = doreamon_1.default.uuid() + '@' + new Date().getTime();
const id = tcpId + ':' + requestId;
const _data = await utils_1.dataProcessor.server.request(data);
domainSocket.emit('request', {
id,
data: _data,
});
ctx.callbackContainer.set(tcpId, requestId, callback);
};
tcpSocket.on('data', data => {
const _data = data.toString();
request(socketConfig.tcpId, _data, (data) => {
if (tcpSocket.writable) {
const buffer = Buffer.from(data, 'base64');
debug('response:', buffer.toString('utf8'));
tcpSocket.write(buffer);
}
});
});
tcpSocket.on('close', () => {
ctx.callbackContainer.remove(socketConfig.tcpId);
});
});
};
return {
attach,
};
}
exports.default = createServer;
function destroy(tcpSocket) {
const data = [
'HTTP/1.1 404 Not Found',
'Content-Type: text/plain; charset=utf-8',
'Content-Length: 9',
`Date: ${new Date().toUTCString()}`,
'Connection: keep-alive',
'Keep-Alive: timeout=5',
'',
'Not Found'
];
tcpSocket.write(data.join('\r\n'));
tcpSocket.destroy();
}