mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-26 01:24:59 +02:00
* fix(relay): proxy fallback for Yahoo/Crypto, isolate OREF proxy, fix Dockerfile Yahoo Finance and CoinPaprika fail from Railway datacenter IPs (rate limiting). Added PROXY_URL fallback to fetchYahooChartDirect (used by 5 seeders) and relay chart proxy endpoint. Added shared _fetchCoinPaprikaTickers with proxy fallback + 5min cache (3 crypto seeders share one fetch). Added CoinPaprika fallback to CryptoSectors (previously had none). Isolated OREF_PROXY_AUTH exclusively for OREF alerts. OpenSky, seed-military-flights, and _proxy-utils now fall back to PROXY_URL instead of the expensive IL-exit proxy. Added seed-climate-news.mjs + _seed-utils.mjs COPY to Dockerfile.relay (missing since PR #2532). Added pizzint bootstrap hydration to cache-keys.ts, bootstrap.js, and src/services/pizzint.ts. * fix(relay): address review — remove unused reverseMap, guard double proxy - Remove dead reverseMap identity map in CryptoSectors Paprika fallback - Add _proxied flag to handleYahooChartRequest._tryProxy to prevent double proxy call on timeout→destroy→error sequence
97 lines
3.2 KiB
JavaScript
97 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Shared proxy configuration parser used by ais-relay.cjs and _seed-utils.mjs.
|
|
*
|
|
* Supported formats for PROXY_URL:
|
|
* - http://user:pass@host:port (standard URL)
|
|
* - host:port:user:pass (Decodo/Smartproxy)
|
|
*
|
|
* Returns { host, port, auth: 'user:pass' } or null.
|
|
*/
|
|
function parseProxyConfig(raw) {
|
|
if (!raw) return null;
|
|
|
|
// Standard URL format: http://user:pass@host:port or https://user:pass@host:port
|
|
try {
|
|
const u = new URL(raw);
|
|
if (u.hostname) {
|
|
return {
|
|
host: u.hostname,
|
|
port: parseInt(u.port, 10),
|
|
auth: u.username ? `${decodeURIComponent(u.username)}:${decodeURIComponent(u.password)}` : null,
|
|
tls: u.protocol === 'https:',
|
|
};
|
|
}
|
|
} catch { /* fall through */ }
|
|
|
|
// Froxy/OREF format: user:pass@host:port
|
|
if (raw.includes('@')) {
|
|
const atIdx = raw.lastIndexOf('@');
|
|
const auth = raw.slice(0, atIdx);
|
|
const hostPort = raw.slice(atIdx + 1);
|
|
const colonIdx = hostPort.lastIndexOf(':');
|
|
if (colonIdx !== -1) {
|
|
const host = hostPort.slice(0, colonIdx);
|
|
const port = parseInt(hostPort.slice(colonIdx + 1), 10);
|
|
if (host && port && auth) return { host, port, auth };
|
|
}
|
|
}
|
|
|
|
// Decodo/Smartproxy format: host:port:user:pass
|
|
const parts = raw.split(':');
|
|
if (parts.length >= 4) {
|
|
const host = parts[0];
|
|
const port = parseInt(parts[1], 10);
|
|
const user = parts[2];
|
|
const pass = parts.slice(3).join(':');
|
|
if (host && port && user) return { host, port, auth: `${user}:${pass}` };
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Resolve proxy from PROXY_URL only. Returns { host, port, auth } or null.
|
|
* Use this for sources where OREF (IL-exit) proxy must NOT be used (e.g. USNI).
|
|
*/
|
|
function resolveProxyConfig() {
|
|
return parseProxyConfig(process.env.PROXY_URL || '');
|
|
}
|
|
|
|
/**
|
|
* Resolve proxy from PROXY_URL only.
|
|
* OREF_PROXY_AUTH is IL-exit and expensive — reserved exclusively for OREF alerts.
|
|
*/
|
|
function resolveProxyConfigWithFallback() {
|
|
return parseProxyConfig(process.env.PROXY_URL || '');
|
|
}
|
|
|
|
/**
|
|
* Returns proxy as "user:pass@host:port" string for use with curl -x.
|
|
* Decodo: gate.decodo.com → us.decodo.com (curl endpoint differs from CONNECT endpoint).
|
|
* Returns empty string if no proxy configured.
|
|
*/
|
|
function resolveProxyString() {
|
|
const cfg = resolveProxyConfigWithFallback();
|
|
if (!cfg) return '';
|
|
const host = cfg.host.replace(/^gate\./, 'us.');
|
|
return cfg.auth ? `${cfg.auth}@${host}:${cfg.port}` : `${host}:${cfg.port}`;
|
|
}
|
|
|
|
/**
|
|
* Returns proxy as "user:pass@host:port" string for use with HTTP CONNECT tunneling.
|
|
* Does NOT replace gate.decodo.com → us.decodo.com; CONNECT endpoint is gate.decodo.com.
|
|
* When PROXY_URL uses https:// (TLS proxy), returns "https://user:pass@host:port" so
|
|
* httpsProxyFetchJson uses tls.connect to the proxy instead of plain net.connect.
|
|
* Returns empty string if no proxy configured.
|
|
*/
|
|
function resolveProxyStringConnect() {
|
|
const cfg = resolveProxyConfigWithFallback();
|
|
if (!cfg) return '';
|
|
const base = cfg.auth ? `${cfg.auth}@${cfg.host}:${cfg.port}` : `${cfg.host}:${cfg.port}`;
|
|
return cfg.tls ? `https://${base}` : base;
|
|
}
|
|
|
|
module.exports = { parseProxyConfig, resolveProxyConfig, resolveProxyConfigWithFallback, resolveProxyString, resolveProxyStringConnect };
|