Duplicate Code Opportunity
Summary
- Pattern:
fetchJson and httpProbe in containers/api-proxy/model-discovery.js share ~25 lines of identical HTTP/HTTPS request setup code (URL parsing, reqOpts construction, settled/resolveOnce pattern, req.on('timeout', ...), req.on('error', ...)). The only differences are in response handling.
- Locations:
containers/api-proxy/model-discovery.js lines ~46–59 (fetchJson) and ~100–113 (httpProbe)
- Impact: Any change to proxy agent configuration, timeout handling, or error logging in request setup must be made in both functions.
Evidence
fetchJson setup (lines ~46–72):
const parsed = new URL(url);
const isHttps = parsed.protocol === 'https:';
const mod = isHttps ? https : http;
const reqOpts = {
hostname: parsed.hostname,
port: parsed.port || (isHttps ? 443 : 80),
path: parsed.pathname + parsed.search,
method: opts.method,
headers: { ...opts.headers },
...(isHttps && proxyAgent ? { agent: proxyAgent } : {}),
timeout: timeoutMs,
};
let settled = false;
const resolveOnce = (value) => { if (settled) return; settled = true; resolve(value); };
const req = mod.request(reqOpts, (res) => { ... });
req.on('timeout', () => { req.destroy(...); });
req.on('error', (err) => { resolveOnce(null); });
req.end();
httpProbe setup (lines ~100–126) is structurally identical — same URL parsing, same reqOpts, same settled/resolveOnce/rejectOnce pattern.
Suggested Refactoring
Extract a buildRequest(url, opts, timeoutMs, onResponse) helper that handles the shared setup:
function buildRequest(url, opts, timeoutMs, onResponse) {
const parsed = new URL(url);
const isHttps = parsed.protocol === 'https:';
const mod = isHttps ? https : http;
const reqOpts = {
hostname: parsed.hostname,
port: parsed.port || (isHttps ? 443 : 80),
path: parsed.pathname + parsed.search,
method: opts.method,
headers: { ...opts.headers },
...(isHttps && proxyAgent ? { agent: proxyAgent } : {}),
timeout: timeoutMs,
};
return { mod, reqOpts };
}
Both fetchJson and httpProbe call buildRequest for setup, then differ only in onResponse logic.
Affected Files
containers/api-proxy/model-discovery.js — fetchJson (~lines 46–95) and httpProbe (~lines 100–130)
Effort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-05-06
Generated by Duplicate Code Detector · ● 564K · ◷
Duplicate Code Opportunity
Summary
fetchJsonandhttpProbeincontainers/api-proxy/model-discovery.jsshare ~25 lines of identical HTTP/HTTPS request setup code (URL parsing,reqOptsconstruction,settled/resolveOncepattern,req.on('timeout', ...),req.on('error', ...)). The only differences are in response handling.containers/api-proxy/model-discovery.jslines ~46–59 (fetchJson) and ~100–113 (httpProbe)Evidence
fetchJsonsetup (lines ~46–72):httpProbesetup (lines ~100–126) is structurally identical — same URL parsing, samereqOpts, samesettled/resolveOnce/rejectOncepattern.Suggested Refactoring
Extract a
buildRequest(url, opts, timeoutMs, onResponse)helper that handles the shared setup:Both
fetchJsonandhttpProbecallbuildRequestfor setup, then differ only inonResponselogic.Affected Files
containers/api-proxy/model-discovery.js—fetchJson(~lines 46–95) andhttpProbe(~lines 100–130)Effort Estimate
Low
Detected by Duplicate Code Detector workflow. Run date: 2026-05-06