Any code that performs network I/O must define (1) routing correctness (proxy vs loopback/local), and (2) a bounded request lifecycle (AbortSignal/timeout) for every path, including fallbacks; and (3) consistent in-flight cancellation/grace semantics on disconnect.
Apply this standard:
Example pattern (bounded + correct dispatcher selection):
const idleTimeoutFreeDispatcher = new EnvHttpProxyAgent({ headersTimeout: 0, bodyTimeout: 0 })
function createRequest(signal: AbortSignal, url: string) {
const isLocal = isLocalModelUrl(url) // must cover 0.0.0.0 + mapped loopback, etc.
// Preserve loopback direct routing when HTTP_PROXY is set.
const dispatcher = isLocal && !isLoopback(url)
? idleTimeoutFreeDispatcher
: /* your normal direct-vs-proxy dispatcher */ undefined
return { dispatcher, signal }
}
async function fetchWithAllPathsBound(url: string, signal: AbortSignal): Promise<Response> {
const { dispatcher } = createRequest(signal, url)
return fetch(url, { dispatcher, signal })
}
async function fetchModelIdsWithFallback(url: string, signal: AbortSignal) {
try {
return await fetchWithAllPathsBound(url, signal)
} catch {
// IMPORTANT: fallback must reuse the same AbortSignal.
return await fetchWithAllPathsBound(url, signal)
}
}
If you do this consistently, you avoid hangs from unbounded fallbacks, prevent proxy/env-var regressions for loopback/local servers, and maintain predictable behavior for in-flight network operations during disconnects/reconnects.