"use strict";
const Util = require('../util');
const ProxyUtil = require('../proxy_util');
const Base = require('./base');
const HttpsOcspAgent = require('../agent/https_ocsp_agent');
const HttpsCrlAgent = require('../agent/https_crl_agent').default;
const HttpsProxyAgent = require('../agent/https_proxy_agent');
const HttpAgent = require('http').Agent;
const GlobalConfig = require('../../lib/global_config');
const Logger = require('../logger');
const RequestUtil = require('../http/request_util');
const { isCrlValidationEnabled } = require('../agent/crl_validator');
/**
 * Creates a client that can be used to make requests in Node.js.
 *
 * @param {ConnectionConfig} connectionConfig
 * @constructor
 */
function NodeHttpClient(connectionConfig) {
    Logger.getInstance().trace('Initializing NodeHttpClient with Connection Config[%s]', connectionConfig.describeIdentityAttributes());
    Base.apply(this, [connectionConfig]);
}
Util.inherits(NodeHttpClient, Base);
const httpsAgentCache = new Map();
function getFromCacheOrCreate(AgentClass, options, agentId) {
    Logger.getInstance().trace('Agent[id: %s] - trying to retrieve from cache or create.', agentId);
    let agent = {};
    function createAgent(AgentClass, agentOptions, agentId) {
        Logger.getInstance().debug('Agent[id: %s] - creating a new agent instance with idle timeout=%dms.', agentId, agentOptions.timeout);
        const agent = new AgentClass(agentOptions);
        httpsAgentCache.set(agentId, agent);
        Logger.getInstance().trace('Agent[id: %s] - new instance stored in cache.', agentId);
        // detect and log PROXY envvar + agent proxy settings
        const compareAndLogEnvAndAgentProxies = ProxyUtil.getCompareAndLogEnvAndAgentProxies(agentOptions);
        Logger.getInstance().debug('Agent[id: %s] - proxy settings used in requests: %s', agentId, compareAndLogEnvAndAgentProxies.messages);
        // if there's anything to warn on (e.g. both envvar + agent proxy used, and they are different)
        // log warnings on them
        if (compareAndLogEnvAndAgentProxies.warnings) {
            Logger.getInstance().warn('Agent[id: %s] - %s', agentId, compareAndLogEnvAndAgentProxies.warnings);
        }
        return agent;
    }
    if (httpsAgentCache.has(agentId)) {
        Logger.getInstance().trace('Agent[id: %s] - retrieving an agent instance from cache.', agentId);
        agent = httpsAgentCache.get(agentId);
    }
    else {
        agent = createAgent(AgentClass, options, agentId);
    }
    return agent;
}
function enrichAgentOptionsWithProxyConfig(agentOptions, proxy) {
    agentOptions.host = proxy.host;
    agentOptions.port = proxy.port;
    agentOptions.protocol = proxy.protocol;
    agentOptions.useForOCSP = proxy.useForOCSP;
    agentOptions.noProxy = proxy.noProxy;
    if (proxy.user && proxy.password) {
        agentOptions.user = proxy.user;
        agentOptions.password = proxy.password;
    }
}
function isBypassProxy(proxy, destination, agentId) {
    const matches = ProxyUtil.isByPassProxy(proxy, destination);
    if (matches) {
        Logger.getInstance().debug('Agent[id: %s] - bypassing proxy allowed for destination: %s', agentId, destination);
        return true;
    }
    return false;
}
/**
 * @inheritDoc
 */
NodeHttpClient.prototype.getAgent = function (parsedUrl, proxy, mock) {
    Logger.getInstance().trace('Agent[url: %s] - getting an agent instance.', RequestUtil.describeURL(parsedUrl.href));
    if (!proxy && GlobalConfig.isEnvProxyActive()) {
        const isHttps = parsedUrl.protocol === 'https:';
        proxy = ProxyUtil.getProxyFromEnv(isHttps);
        if (proxy) {
            Logger.getInstance().debug('Agent[url: %s] - proxy info loaded from the environment variable. Proxy host: %s', RequestUtil.describeURL(parsedUrl.href), proxy.host);
        }
    }
    return getProxyAgent(proxy, parsedUrl, parsedUrl.href, mock, this._connectionConfig);
};
function getProxyAgent(proxyOptions, parsedUrl, destination, mock, connectionConfig) {
    Logger.getInstance().trace('Agent[url: %s] - getting a proxy agent instance.', RequestUtil.describeURL(parsedUrl.href));
    const agentOptions = {
        protocol: parsedUrl.protocol,
        hostname: parsedUrl.hostname,
        keepAlive: GlobalConfig.getKeepAlive(),
        // Idle socket timeout in milliseconds - only affects inactive sockets.
        // Does not affect pending requests.
        timeout: 30 * 1000,
    };
    if (mock) {
        const mockAgent = mock.agentClass(agentOptions);
        if (mockAgent.protocol === parsedUrl.protocol) {
            Logger.getInstance().debug('Agent[url: %s] - the mock agent will be used.', RequestUtil.describeURL(parsedUrl.href));
            return mockAgent;
        }
    }
    const destHost = ProxyUtil.getHostFromURL(destination);
    const agentId = createAgentId({
        protocol: agentOptions.protocol,
        hostname: agentOptions.hostname,
        destination: destHost,
        keepAlive: agentOptions.keepAlive,
        connectionConfig,
    });
    Logger.getInstance().debug('Agent[id: %s] - the destination host is: %s.', agentId, destHost);
    const bypassProxy = isBypassProxy(proxyOptions, destination, agentId);
    let agent;
    const isHttps = agentOptions.protocol === 'https:';
    if (isHttps) {
        agentOptions.crlValidatorConfig = connectionConfig.crlValidatorConfig;
        if (proxyOptions && !bypassProxy) {
            Logger.getInstance().trace('Agent[id: %s] - using HTTPS agent enriched with proxy options.', agentId);
            enrichAgentOptionsWithProxyConfig(agentOptions, proxyOptions);
            agent = getFromCacheOrCreate(HttpsProxyAgent, agentOptions, agentId);
        }
        else {
            const AgentClass = isCrlValidationEnabled(connectionConfig.crlValidatorConfig)
                ? HttpsCrlAgent
                : HttpsOcspAgent;
            Logger.getInstance().trace(`Agent[id: %s] - using ${AgentClass.name} agent without proxy.`, agentId);
            agent = getFromCacheOrCreate(AgentClass, agentOptions, agentId);
        }
    }
    else if (proxyOptions && !bypassProxy) {
        Logger.getInstance().trace('Agent[id: %s] - using HTTP agent enriched with proxy options.', agentId);
        enrichAgentOptionsWithProxyConfig(agentOptions, proxyOptions);
        agent = getFromCacheOrCreate(HttpAgent, agentOptions, agentId);
    }
    else {
        Logger.getInstance().trace('Agent[id: %s] - using HTTP agent without proxy.', agentId);
        agent = getFromCacheOrCreate(HttpAgent, agentOptions, agentId);
    }
    return agent;
}
function createAgentId({ protocol, hostname, destination, keepAlive, connectionConfig }) {
    return [
        protocol,
        hostname,
        destination,
        keepAlive ? 'keepAlive' : 'noKeepAlive',
        `crl:${connectionConfig.crlValidatorConfig.checkMode}`,
    ].join('-');
}
module.exports = { NodeHttpClient, getProxyAgent, isBypassProxy, httpsAgentCache };
//# sourceMappingURL=node_untyped.js.map