Commit Graph

6 Commits

Author SHA1 Message Date
Elie Habib
15bd6f31ca refactor: consolidate proxy tunnel into shared _proxy-utils.cjs (#2702)
* refactor: consolidate 5 proxy tunnel implementations into _proxy-utils.cjs

5 near-identical HTTP CONNECT proxy tunnel implementations (3 in
ais-relay.cjs, 1 in _seed-utils.mjs, 1 in seed-military-flights.mjs)
consolidated into two shared functions in _proxy-utils.cjs:

- proxyConnectTunnel(): low-level CONNECT + TLS wrapping, returns socket
- proxyFetch(): high-level fetch with decompression, custom headers,
  POST support, timeout

All consumers now call the shared implementation:
- _seed-utils.mjs httpsProxyFetchRaw: 75 lines -> 6 lines
- ais-relay.cjs ytFetchViaProxy: 40 lines -> 5 lines
- ais-relay.cjs _openskyProxyConnect: 35 lines -> 8 lines
- ais-relay.cjs inline Dodo CONNECT: 25 lines -> 10 lines
- seed-military-flights.mjs proxyFetchJson: 70 lines -> 14 lines

Also wires weather alerts proxy fallback (fixes STALE_SEED health crit).

Net: -104 lines. Resolves the TODO at _seed-utils.mjs:311.

* fix(proxy): default tls=true for bare proxy strings

parseProxyConfig returned no tls field for bare-format proxies
(user:pass@host:port and host:port:user:pass). proxyConnectTunnel
checked proxyConfig.tls and used plain TCP when it was undefined,
breaking connections to Decodo which requires TLS. Only http:// URLs
should use plain TCP.

* fix(proxy): timeout covers full response, pass targetPort through

- Move clearTimeout from header arrival to stream end, so a server
  that stalls after 200 OK headers still hits the timeout
- Make targetPort configurable in proxyConnectTunnel (was hardcoded
  443), pass through from _openskyProxyConnect
2026-04-05 08:01:27 +04:00
Elie Habib
d04852bf02 fix(relay): proxy fallback for Yahoo/Crypto, isolate OREF proxy (#2627)
* 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
2026-04-03 00:08:37 +04:00
Elie Habib
bf27e474c2 fix(seeder): TLS proxy CONNECT — fixes FRED fetch failures (FSI, yield curve, macro) (#2538)
* fix(seeder): use TLS for proxy CONNECT tunnel to fix FRED fetch failures

Decodo gate.decodo.com:10001 requires TLS. Previous code used http.request
(plain TCP) which received SOCKS5 rejection bytes instead of HTTP 200.

Two issues fixed:
1. Replace http.request CONNECT with tls.connect + manual CONNECT handshake.
   Node.js http.request also auto-sets Host to the proxy hostname; Decodo
   rejects this and responds with SOCKS5 bytes (0x05 0xff). Manual CONNECT
   over a raw TLS socket avoids both issues.
2. Handle https:// and plain "user:pass@host:port" proxy URL formats — always
   uses TLS regardless of PROXY_URL prefix.

_proxy-utils.cjs: resolveProxyStringConnect now preserves https:// prefix
from PROXY_URL so callers can detect TLS proxies explicitly.

All 24 FRED series (BAMLH0A0HYM2, FEDFUNDS, DGS10, etc.) confirmed working
locally via gate.decodo.com:10001.

* fix(seeder): respect http:// proxy scheme + buffer full CONNECT response

Two protocol-correctness fixes:

1. http:// proxies used plain TCP before; always-TLS regressed them.
   Now: bare/undeclared format → TLS (Decodo requires it), explicit
   http:// → plain net.connect, explicit https:// → TLS.

2. CONNECT response buffered until \r\n\r\n instead of acting on the
   first data chunk. Fragmented proxy responses (headers split across
   packets) could corrupt the TLS handshake by leaving header bytes
   on the wire when tls.connect() was called too early.

Verified locally: BAMLH0A0HYM2 → { date: 2026-03-26, value: 3.21 }

* chore(seeder): remove unused http import, fix stale JSDoc

- Drop `import * as http from 'node:http'` — no longer used after
  replacing http.request CONNECT with tls.connect + manual handshake
- Update resolveProxyStringConnect() JSDoc: https.request → tls.connect
2026-03-30 11:06:48 +04:00
Elie Habib
a49f6eb53e fix(seed-economy): use gate.decodo.com for FRED CONNECT proxy, add fallback logging (#2511)
* fix(seed-economy): use gate.decodo.com for FRED CONNECT proxy, add fallback logging

resolveProxyString() replaces gate. → us.decodo.com for curl compatibility,
but httpsProxyFetchJson uses HTTP CONNECT tunneling which requires gate.decodo.com.
All FRED series were silently failing with "Parse Error: Expected HTTP/, RTSP/ or ICE/"
because us.decodo.com doesn't respond to CONNECT with valid HTTP.

- Add resolveProxyStringConnect() in _proxy-utils.cjs (no host replacement)
- Export resolveProxyForConnect() from _seed-utils.mjs for CONNECT-based proxy
- seed-economy: _proxyAuth uses resolveProxyForConnect() (FRED), _curlProxyAuth uses resolveProxy() (Yahoo)
- fredFetchJson now logs when direct fails and proxy is tried, labels proxy errors as "proxy: ..."

* fix(seed-economy): roll out resolveProxyForConnect to all FRED seeders

seed-economic-calendar, seed-supply-chain-trade, and seed-bls-series were
still passing the curl-oriented us.decodo.com proxy string to fredFetchJson,
which uses HTTP CONNECT tunneling and requires gate.decodo.com.
2026-03-29 17:26:51 +04:00
Elie Habib
f5a1512d65 fix(usni): use https.request for proxy CONNECT (Decodo port 10001 is HTTPS) (#2408) 2026-03-28 11:32:53 +04:00
Elie Habib
f56e7c24ad refactor(proxy): extract shared _proxy-utils.cjs, support Decodo host:port:user:pass format (#2399)
Previously each seeder (ais-relay.cjs, _seed-utils.mjs, seed-fear-greed.mjs,
seed-disease-outbreaks.mjs) had its own inline resolveProxy() with slightly
different implementations. This caused USNI seeding to fail because
parseProxyUrl() only handled URL format while PROXY_URL uses Decodo
host:port:user:pass format.

- Add scripts/_proxy-utils.cjs with parseProxyConfig(), resolveProxyConfig(),
  resolveProxyString() handling both http://user:pass@host:port and
  host:port:user:pass formats
- ais-relay.cjs: require _proxy-utils.cjs, alias parseProxyUrl = parseProxyConfig
- _seed-utils.mjs: import resolveProxyString via createRequire, delegate resolveProxy()
- seed-fear-greed.mjs, seed-disease-outbreaks.mjs: remove inline resolveProxy(),
  import from _seed-utils.mjs instead
2026-03-28 08:35:19 +04:00