"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getThrottleIntervalMs = exports.getConcurrentRequestsLimit = exports.applyHostRule = exports.findMatchingRule = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const global_1 = require("../../config/global");
const constants_1 = require("../../constants");
const logger_1 = require("../../logger");
const proxy_1 = require("../../proxy");
const hostRules = tslib_1.__importStar(require("../host-rules"));
const string_match_1 = require("../string-match");
const url_1 = require("../url");
const dns_1 = require("./dns");
const keep_alive_1 = require("./keep-alive");
function findMatchingRule(url, options) {
    const { hostType } = options;
    let res = hostRules.find({ hostType, url });
    if (is_1.default.nonEmptyString(res.token) ||
        is_1.default.nonEmptyString(res.username) ||
        is_1.default.nonEmptyString(res.password)) {
        // do not fallback if we already have auth infos
        return res;
    }
    // Fallback to `github` hostType
    if (hostType &&
        constants_1.GITHUB_API_USING_HOST_TYPES.includes(hostType) &&
        hostType !== 'github') {
        res = {
            ...hostRules.find({
                hostType: 'github',
                url,
            }),
            ...res,
        };
    }
    // Fallback to `gitlab` hostType
    if (hostType &&
        constants_1.GITLAB_API_USING_HOST_TYPES.includes(hostType) &&
        hostType !== 'gitlab') {
        res = {
            ...hostRules.find({
                hostType: 'gitlab',
                url,
            }),
            ...res,
        };
    }
    // Fallback to `bitbucket` hostType
    if (hostType &&
        constants_1.BITBUCKET_API_USING_HOST_TYPES.includes(hostType) &&
        hostType !== 'bitbucket') {
        res = {
            ...hostRules.find({
                hostType: 'bitbucket',
                url,
            }),
            ...res,
        };
    }
    // Fallback to `gitea` hostType
    if (hostType &&
        constants_1.GITEA_API_USING_HOST_TYPES.includes(hostType) &&
        hostType !== 'gitea') {
        res = {
            ...hostRules.find({
                hostType: 'gitea',
                url,
            }),
            ...res,
        };
    }
    return res;
}
exports.findMatchingRule = findMatchingRule;
// Apply host rules to requests
function applyHostRule(url, options, hostRule) {
    const { username, password, token, enabled, authType } = hostRule;
    const host = (0, url_1.parseUrl)(url)?.host;
    if (options.noAuth) {
        logger_1.logger.trace({ url }, `Authorization disabled`);
    }
    else if (is_1.default.nonEmptyString(options.headers?.authorization) ||
        is_1.default.nonEmptyString(options.password) ||
        is_1.default.nonEmptyString(options.token)) {
        logger_1.logger.once.debug(`hostRules: authentication already set for ${host}`);
        logger_1.logger.trace({ url }, `Authorization already set`);
    }
    else if (password !== undefined) {
        logger_1.logger.once.debug(`hostRules: applying Basic authentication for ${host}`);
        logger_1.logger.trace({ url }, `Applying Basic authentication`);
        options.username = username;
        options.password = password;
    }
    else if (token) {
        logger_1.logger.once.debug(`hostRules: applying Bearer authentication for ${host}`);
        logger_1.logger.trace({ url }, `Applying Bearer authentication`);
        options.token = token;
        options.context = { ...options.context, authType };
    }
    else if (enabled === false) {
        options.enabled = false;
    }
    else {
        logger_1.logger.once.debug(`hostRules: no authentication for ${host}`);
    }
    // Apply optional params
    if (hostRule.abortOnError) {
        options.abortOnError = hostRule.abortOnError;
    }
    if (hostRule.abortIgnoreStatusCodes) {
        options.abortIgnoreStatusCodes = hostRule.abortIgnoreStatusCodes;
    }
    if (hostRule.timeout) {
        options.timeout = hostRule.timeout;
    }
    if (hostRule.dnsCache) {
        options.lookup = dns_1.dnsLookup;
    }
    if (hostRule.headers) {
        const allowedHeaders = global_1.GlobalConfig.get('allowedHeaders', []);
        const filteredHeaders = {};
        for (const [header, value] of Object.entries(hostRule.headers)) {
            if ((0, string_match_1.anyMatchRegexOrMinimatch)(header, allowedHeaders)) {
                filteredHeaders[header] = value;
            }
            else {
                logger_1.logger.once.error({ allowedHeaders, header }, 'Disallowed hostRules headers');
            }
        }
        options.headers = {
            ...filteredHeaders,
            ...options.headers,
        };
    }
    if (hostRule.keepAlive) {
        options.agent = keep_alive_1.keepAliveAgents;
    }
    if (!(0, proxy_1.hasProxy)() && hostRule.enableHttp2 === true) {
        options.http2 = true;
    }
    if (is_1.default.nonEmptyString(hostRule.httpsCertificateAuthority)) {
        options.https = {
            ...(options.https ?? {}),
            certificateAuthority: hostRule.httpsCertificateAuthority,
        };
    }
    if (is_1.default.nonEmptyString(hostRule.httpsPrivateKey)) {
        options.https = {
            ...(options.https ?? {}),
            key: hostRule.httpsPrivateKey,
        };
    }
    if (is_1.default.nonEmptyString(hostRule.httpsCertificate)) {
        options.https = {
            ...(options.https ?? {}),
            certificate: hostRule.httpsCertificate,
        };
    }
    return options;
}
exports.applyHostRule = applyHostRule;
function getConcurrentRequestsLimit(url) {
    const { concurrentRequestLimit } = hostRules.find({ url });
    return is_1.default.number(concurrentRequestLimit) && concurrentRequestLimit > 0
        ? concurrentRequestLimit
        : null;
}
exports.getConcurrentRequestsLimit = getConcurrentRequestsLimit;
function getThrottleIntervalMs(url) {
    const { maxRequestsPerSecond } = hostRules.find({ url });
    return is_1.default.number(maxRequestsPerSecond) && maxRequestsPerSecond > 0
        ? Math.ceil(1000 / maxRequestsPerSecond)
        : null;
}
exports.getThrottleIntervalMs = getThrottleIntervalMs;
//# sourceMappingURL=host-rules.js.map