"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IpLookupServices = exports.httpGet = void 0;
const http = require("http");
const https = require("https");
const url = require("url");
async function lookupPublicIp(ipLookupServiceUrl = exports.IpLookupServices.ipify, agent, proxyUrl) {
    if (!ipLookupServiceUrl.startsWith('http'))
        ipLookupServiceUrl = `https://${ipLookupServiceUrl}`;
    if (proxyUrl && proxyUrl.startsWith('http')) {
        // require https for lookup services over http proxies
        ipLookupServiceUrl.replace('http://', 'https://');
    }
    const lookupService = parse(ipLookupServiceUrl);
    const port = lookupService.port ?? lookupService.protocol === 'https:' ? 443 : 80;
    const requestOptions = {
        method: 'GET',
    };
    let socketWrapper;
    if (agent) {
        socketWrapper = await agent.createSocketConnection({
            host: lookupService.host,
            port: String(port),
            servername: lookupService.host,
            keepAlive: false,
            isSsl: ipLookupServiceUrl.startsWith('https'),
            proxyUrl,
        });
        requestOptions.createConnection = () => socketWrapper.socket;
        requestOptions.agent = null;
    }
    try {
        return await httpGet(ipLookupServiceUrl, requestOptions);
    }
    finally {
        if (socketWrapper)
            socketWrapper.close();
    }
}
exports.default = lookupPublicIp;
function httpGet(requestUrl, requestOptions) {
    const httpModule = requestUrl.startsWith('https') ? https : http;
    return new Promise((resolve, reject) => {
        const request = httpModule.request(requestUrl, requestOptions, async (res) => {
            if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
                resolve(httpGet(res.headers.location, requestOptions));
                return;
            }
            res.on('error', reject);
            res.setEncoding('utf8');
            let result = '';
            for await (const chunk of res) {
                result += chunk;
            }
            resolve(result);
        });
        request.on('error', reject);
        request.end();
    });
}
exports.httpGet = httpGet;
const parsedLookupServicesByUrl = new Map();
function parse(requestUrl) {
    if (!parsedLookupServicesByUrl.has(requestUrl)) {
        const options = url.parse(requestUrl);
        options.port || (options.port = requestUrl.startsWith('https') ? '443' : '80');
        parsedLookupServicesByUrl.set(requestUrl, options);
    }
    return parsedLookupServicesByUrl.get(requestUrl);
}
exports.IpLookupServices = {
    ipify: 'api.ipify.org',
    icanhazip: 'icanhazip.com',
    aws: 'checkip.amazonaws.com',
    identMe: 'ident.me',
    ifconfigMe: 'ifconfig.me/ip',
    ipecho: 'ipecho.net/plain',
    ipinfo: 'ipinfo.io/ip',
    opendns: 'diagnostic.opendns.com/myip',
};
//# sourceMappingURL=lookupPublicIp.js.map