"use strict";
/*
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,
};
