fix: in the case of outbound_proxy, public-ip-detection could be wrong, so we'll first try without the proxy

Massimo Melina committed Dec 3, 2025 at 18:36 UTC d1b5dc5ce6fc0015d8bc985b8120440e4f55aeb8
2 files changed +11 -4
src/nat.ts
+9 -3
@@ -4,7 +4,7 @@ import { debounceAsync } from './debounceAsync'
4 import { haveTimeout, HOUR, inCommon, ipForUrl, MINUTE, promiseBestEffort, repeat, wantArray } from './cross'
5 import { getProjectInfo } from './github'
6 import _ from 'lodash'
7 -import { httpString } from './util-http'
7 +import { httpStream, httpString } from './util-http'
8 import { Resolver } from 'dns/promises'
9 import { isIP } from 'net'
10 import { getIps, getServerStatus } from './listen'
@@ -49,8 +49,14 @@ export const getPublicIps = debounceAsync(async () => {
49 if (typeof svc === 'string')
50 svc = { type: 'http', url: svc }
51 console.debug("trying ip service", svc.url || svc.name)
52 - if (svc.type === 'http')
53 - return httpString(svc.url, { timeout: 5_000 })
52 + if (svc.type === 'http') {
53 + const timeout = 5_000
54 + return httpString(svc.url, { timeout, proxy: '' }).catch(e => { // first try without a proxy
55 + if (!e.cause?.statusCode && httpStream.defaultProxy) // only for network errors (not http, where we have statusCode), retry using the proxy (if any)
56 + return httpString(svc.url, { timeout })
57 + throw e
58 + })
59 + }
60 if (svc.type !== 'dns') throw "unsupported"
61 const resolver = new Resolver({ timeout: 2_000 })
62 resolver.setServers(svc.ips)
src/util-http.ts
+2 -1
@@ -96,7 +96,8 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
96 }).on('error', (e: any) => {
97 if (proxy && e?.code === 'ECONNREFUSED')
98 console.debug("cannot connect to proxy ", proxy)
99 - reject((req as any).res || e)
99 + e.cause ??= req // enrich the error
100 + reject(e)
101 })
102 if (body && body instanceof Readable)
103 body.pipe(req).on('end', () => req.end())