http-proxy-3
Version:
Modern rewrite of http-proxy
167 lines (164 loc) • 6.38 kB
JavaScript
;
/*
The passes.
A `pass` is just a function that is executed on `req, res, options`
so that you can easily add new checks while still keeping the base
flexible.
NOTE: The function in OUTGOING_PASSES are called. They are assumed
to not return anything.
*/
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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.OUTGOING_PASSES = void 0;
exports.removeChunked = removeChunked;
exports.setConnection = setConnection;
exports.setRedirectHostRewrite = setRedirectHostRewrite;
exports.writeHeaders = writeHeaders;
exports.writeStatusCode = writeStatusCode;
const common = __importStar(require("../common"));
const redirectRegex = /^201|30(1|2|7|8)$/;
// <--
// If is a HTTP 1.0 request, remove chunk headers
function removeChunked(_req, _res,
// Response object from the proxy request
proxyRes) {
// transfer-encoding is hop-by-hop, don't preserve it across proxy hops
delete proxyRes.headers["transfer-encoding"];
}
// If is a HTTP 1.0 request, set the correct connection header
// or if connection header not present, then use `keep-alive`
function setConnection(req, _res,
// Response object from the proxy request
proxyRes) {
if (req.httpVersion === "1.0") {
proxyRes.headers["connection"] = req.headers["connection"] || "close";
}
else if (req.httpVersion !== "2.0" && !proxyRes.headers["connection"]) {
proxyRes.headers["connection"] = req.headers["connection"] || "keep-alive";
}
}
function setRedirectHostRewrite(req, _res, proxyRes, options) {
if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite) &&
proxyRes.headers["location"] &&
redirectRegex.test(`${proxyRes.statusCode}`)) {
const target = common.toURL(options.target);
const location = proxyRes.headers["location"];
if (typeof location != "string") {
return;
}
const u = common.toURL(location);
// make sure the redirected host matches the target host before rewriting
if (target.host != u.host) {
return;
}
if (options.hostRewrite) {
u.host = options.hostRewrite;
}
else if (options.autoRewrite) {
u.host = req.headers[":authority"] ?? req.headers["host"] ?? "";
}
if (options.protocolRewrite) {
u.protocol = options.protocolRewrite;
}
proxyRes.headers["location"] = u.toString();
}
}
// Copy headers from proxyRes to res.
function writeHeaders(_req,
// Response to set headers in
res,
// Response object from the proxy request
proxyRes,
// options.cookieDomainRewrite: Config to rewrite cookie domain
options) {
const rewriteCookieDomainConfig = typeof options.cookieDomainRewrite === "string"
? // also test for ''
{ "*": options.cookieDomainRewrite }
: options.cookieDomainRewrite;
const rewriteCookiePathConfig = typeof options.cookiePathRewrite === "string"
? // also test for ''
{ "*": options.cookiePathRewrite }
: options.cookiePathRewrite;
const preserveHeaderKeyCase = options.preserveHeaderKeyCase;
const setHeader = (key, header) => {
if (header == undefined) {
return;
}
if (rewriteCookieDomainConfig && key.toLowerCase() === "set-cookie") {
header = common.rewriteCookieProperty(header, rewriteCookieDomainConfig, "domain");
}
if (rewriteCookiePathConfig && key.toLowerCase() === "set-cookie") {
header = common.rewriteCookieProperty(header, rewriteCookiePathConfig, "path");
}
res.setHeader(String(key).trim(), header);
};
// message.rawHeaders is added in: v0.11.6
// https://nodejs.org/api/http.html#http_message_rawheaders
let rawHeaderKeyMap;
if (preserveHeaderKeyCase && proxyRes.rawHeaders != undefined) {
rawHeaderKeyMap = {};
for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) {
const key = proxyRes.rawHeaders[i];
rawHeaderKeyMap[key.toLowerCase()] = key;
}
}
for (const key0 in proxyRes.headers) {
let key = key0;
if (_req.httpVersionMajor > 1 && (key === "connection" || key === "keep-alive")) {
// don't send connection header to http2 client
continue;
}
const header = proxyRes.headers[key];
if (preserveHeaderKeyCase && rawHeaderKeyMap) {
key = rawHeaderKeyMap[key] ?? key;
}
setHeader(key, header);
}
}
// Set the statusCode from the proxyResponse
function writeStatusCode(_req, res, proxyRes) {
// From Node.js docs: response.writeHead(statusCode[, statusMessage][, headers])
res.statusCode = proxyRes.statusCode;
if (proxyRes.statusMessage && _req.httpVersionMajor === 1) {
res.statusMessage = proxyRes.statusMessage;
}
}
exports.OUTGOING_PASSES = {
removeChunked,
setConnection,
setRedirectHostRewrite,
writeHeaders,
writeStatusCode,
};