(opts: {
proxyUrl: string;
envUser?: string;
envPass?: string;
})
| 38 | * ambiguous credentials (set in both URL and env). |
| 39 | */ |
| 40 | export function parseProxyConfig(opts: { |
| 41 | proxyUrl: string; |
| 42 | envUser?: string; |
| 43 | envPass?: string; |
| 44 | }): ParsedProxyConfig { |
| 45 | let url: URL; |
| 46 | try { |
| 47 | url = new URL(opts.proxyUrl); |
| 48 | } catch { |
| 49 | throw new ProxyConfigError( |
| 50 | 'expected scheme://[user:pass@]host:port', |
| 51 | `invalid proxy URL — could not parse`, |
| 52 | ); |
| 53 | } |
| 54 | |
| 55 | const scheme = url.protocol.replace(':', ''); |
| 56 | if (scheme !== 'socks5' && scheme !== 'http' && scheme !== 'https') { |
| 57 | throw new ProxyConfigError( |
| 58 | 'use socks5://, http://, or https://', |
| 59 | `unsupported proxy scheme '${scheme}'`, |
| 60 | ); |
| 61 | } |
| 62 | |
| 63 | if (!url.hostname) { |
| 64 | throw new ProxyConfigError( |
| 65 | 'expected scheme://[user:pass@]host:port', |
| 66 | `invalid proxy URL — missing host`, |
| 67 | ); |
| 68 | } |
| 69 | |
| 70 | const port = url.port |
| 71 | ? parseInt(url.port, 10) |
| 72 | : (scheme === 'http' ? 80 : scheme === 'https' ? 443 : 1080); |
| 73 | if (!Number.isInteger(port) || port <= 0 || port > 65535) { |
| 74 | throw new ProxyConfigError( |
| 75 | 'expected scheme://[user:pass@]host:port', |
| 76 | `invalid proxy URL — bad port`, |
| 77 | ); |
| 78 | } |
| 79 | |
| 80 | const urlHasUser = !!url.username; |
| 81 | const urlHasPass = !!url.password; |
| 82 | const envHasUser = !!opts.envUser; |
| 83 | const envHasPass = !!opts.envPass; |
| 84 | const urlHasCreds = urlHasUser || urlHasPass; |
| 85 | const envHasCreds = envHasUser || envHasPass; |
| 86 | |
| 87 | // D9 (codex correction): refuse on mixed sources. Silent override is a |
| 88 | // debugging trap — when a stale BROWSE_PROXY_USER from a prior session |
| 89 | // wins over a fresh --proxy URL, the user can't tell why. |
| 90 | if (urlHasCreds && envHasCreds) { |
| 91 | throw new ProxyConfigError( |
| 92 | 'unset BROWSE_PROXY_USER/PASS or remove user:pass@ from --proxy', |
| 93 | `proxy creds set in both env (BROWSE_PROXY_USER) and URL — pick one source`, |
| 94 | ); |
| 95 | } |
| 96 | |
| 97 | let userId: string | undefined; |
no outgoing calls
no test coverage detected