@duongtrungnguyen/nestro
Version:
Service registry for Nest JS
134 lines • 4.89 kB
JavaScript
import { URL } from "url";
import { SSL_PROTOCOL_REGEX, UPGRADE_HEADER_REGEX, WEBSOCKET_UPGRADE_REGEX, SOCKET_IO_PATH_REGEX, WEBSOCKET_UPGRADE_HEADER } from "./constants";
function setupOutgoing(outgoing = {}, options, req, forward) {
const targetKey = forward || "target";
const target = options[targetKey];
if (!target) {
return outgoing;
}
outgoing.port = getTargetPort(target);
copyTargetProperties(outgoing, target);
outgoing.method = req.method || "GET";
outgoing.headers = req.headers;
if (SSL_PROTOCOL_REGEX.test(target.protocol || "")) {
outgoing.rejectUnauthorized = options.secure !== void 0 ? options.secure : true;
}
outgoing.localAddress = options.localAddress;
configureConnectionHeader(outgoing, req);
const originalPath = req.url || "/";
const rewrittenPath = rewritePath(originalPath, req, options);
outgoing.path = buildPath(target, rewrittenPath, options);
if (options.changeOrigin) {
const hostHeader = getHostHeader(outgoing);
if (hostHeader) {
outgoing.headers.host = hostHeader;
}
}
return outgoing;
}
function getTargetPort(target) {
if (target.port) {
return target.port;
}
if (target.port) {
return parseInt(target.port, 10);
}
return SSL_PROTOCOL_REGEX.test(target.protocol || "") ? 443 : 80;
}
function copyTargetProperties(outgoing, target) {
const props = ["host", "hostname", "socketPath", "pfx", "key", "passphrase", "cert", "ca", "ciphers", "secureProtocol"];
for (const prop of props) {
if (target[prop] !== void 0) {
outgoing[prop] = target[prop];
}
}
}
function configureConnectionHeader(outgoing, req) {
const isWebSocket = req.headers.upgrade && WEBSOCKET_UPGRADE_REGEX.test(req.headers.upgrade.toLowerCase()) && req.headers.connection && UPGRADE_HEADER_REGEX.test(req.headers.connection.toLowerCase());
outgoing.headers = outgoing.headers || {};
if (isWebSocket) {
if (!outgoing.headers.connection) {
outgoing.headers.connection = "upgrade";
}
} else if (!outgoing.agent && !outgoing.headers.connection) {
outgoing.headers.connection = "close";
}
}
function buildPath(target, rewrittenPath, options) {
let targetPath = "";
if (options.prependPath !== false) {
targetPath = target.path || target.pathname || "";
}
const url = new URL(rewrittenPath, "http://localhost");
const pathname = options.toProxy ? rewrittenPath : url.pathname;
const queryString = options.toProxy ? "" : url.search;
const fullPath = joinPaths(targetPath, pathname);
return fullPath + queryString;
}
function rewritePath(path, req, options) {
if (options.ignorePath) return "";
if (!options.pathRewrite) return path;
for (const [pattern, replacement] of Object.entries(options.pathRewrite)) {
const regex = new RegExp(pattern);
if (regex.test(path)) {
return typeof replacement === "function" ? replacement(path, req) : path.replace(regex, replacement);
}
}
return path;
}
function getHostHeader(outgoing) {
if (outgoing.port !== 80 && outgoing.port !== 443) {
return `${outgoing.hostname || outgoing.host}:${outgoing.port}`;
}
return outgoing.hostname || outgoing.host;
}
function joinPaths(...paths) {
if (!paths.length) return "";
const filteredPaths = paths.filter(Boolean);
if (!filteredPaths.length) return "";
return filteredPaths.join("/").replace(/\/+/g, "/").replace(/http:\/|https:\//g, (match) => match.replace(":/", "://"));
}
function setupSocket(socket) {
socket.setTimeout(0);
socket.setNoDelay(true);
socket.setKeepAlive(true, 0);
return socket;
}
function hasEncryptedConnection(req) {
const socket = req.socket;
return Boolean(socket.encrypted || socket.pair);
}
function urlJoin(...args) {
if (!args.length) return "";
const last = args[args.length - 1];
const [path, ...queryParts] = last.split("?");
const paths = [...args.slice(0, -1), path].filter(Boolean);
const joinedPath = joinPaths(...paths);
return queryParts.length > 0 ? `${joinedPath}?${queryParts.join("?")}` : joinedPath;
}
function rewriteCookieProperty(header, config, property) {
if (Array.isArray(header)) {
return header.map((h) => rewriteCookieProperty(h, config, property));
}
const pattern = new RegExp(`(;\\s*${property}=)([^;]+)`, "i");
return header.replace(pattern, (match, prefix, previousValue) => {
const newValue = previousValue in config ? config[previousValue] : config["*"];
return newValue ? `${prefix}${newValue}` : "";
});
}
function isSocketIORequest(req) {
return !!req.url && SOCKET_IO_PATH_REGEX.test(req.url);
}
function isSocketRequest(req) {
return !!req.headers.upgrade && req.headers.upgrade.toLowerCase() === WEBSOCKET_UPGRADE_HEADER;
}
export {
hasEncryptedConnection,
isSocketIORequest,
isSocketRequest,
rewriteCookieProperty,
setupOutgoing,
setupSocket,
urlJoin
};
//# sourceMappingURL=utils.js.map