diff --git a/api/src/config.js b/api/src/config.js index 8784bac0..2d8ac7a0 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -3,12 +3,12 @@ import { loadEnvs, validateEnvs } from "./core/env.js"; const version = await getVersion(); +const canonicalEnv = Object.freeze(structuredClone(process.env)); const env = loadEnvs(); const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"; const cobaltUserAgent = `cobalt/${version} (+https://github.com/imputnet/cobalt)`; -export const canonicalEnv = Object.freeze(structuredClone(process.env)); export const setTunnelPort = (port) => env.tunnelPort = port; export const isCluster = env.instanceCount > 1; export const updateEnv = (newEnv) => { @@ -35,6 +35,7 @@ await validateEnvs(env); export { env, + canonicalEnv, genericUserAgent, cobaltUserAgent, } diff --git a/api/src/core/api.js b/api/src/core/api.js index 0db4d222..d1f6545a 100644 --- a/api/src/core/api.js +++ b/api/src/core/api.js @@ -337,10 +337,15 @@ export const runAPI = async (express, app, __dirname, isPrimary = true) => { randomizeCiphers(); setInterval(randomizeCiphers, 1000 * 60 * 30); // shuffle ciphers every 30 minutes - env.subscribe('externalProxy', () => { + env.subscribe(['externalProxy', 'httpProxyValues'], () => { // TODO: remove env.externalProxy in a future version + const options = {}; + if (env.externalProxy) { + options.httpProxy = env.externalProxy; + } + setGlobalDispatcher( - new EnvHttpProxyAgent({ httpProxy: env.externalProxy || undefined }) + new EnvHttpProxyAgent(options) ); }); diff --git a/api/src/core/env.js b/api/src/core/env.js index 1a7a33bb..519074db 100644 --- a/api/src/core/env.js +++ b/api/src/core/env.js @@ -10,6 +10,10 @@ import { Green, Yellow } from "../misc/console-text.js"; const forceLocalProcessingOptions = ["never", "session", "always"]; const youtubeHlsOptions = ["never", "key", "always"]; +const httpProxyVariables = ["NO_PROXY", "HTTP_PROXY", "HTTPS_PROXY"].flatMap( + k => [ k, k.toLowerCase() ] +); + const changeCallbacks = {}; const onEnvChanged = (changes) => { @@ -43,6 +47,18 @@ export const loadEnvs = (env = process.env) => { } })); + // we need to copy the proxy envs (HTTP_PROXY, HTTPS_PROXY) + // back into process.env, so that EnvHttpProxyAgent can pick + // them up later + for (const key of httpProxyVariables) { + const value = env[key] ?? canonicalEnv[key]; + if (value !== undefined) { + process.env[key] = env[key]; + } else { + delete process.env[key]; + } + } + return { apiURL: env.API_URL || '', apiPort: env.API_PORT || 9000, @@ -79,6 +95,9 @@ export const loadEnvs = (env = process.env) => { externalProxy: env.API_EXTERNAL_PROXY, + // used only for comparing against old values when envs are being updated + httpProxyValues: httpProxyVariables.map(k => String(env[k])).join(''), + turnstileSitekey: env.TURNSTILE_SITEKEY, turnstileSecret: env.TURNSTILE_SECRET, jwtSecret: env.JWT_SECRET, @@ -202,7 +221,8 @@ const wrapReload = (contents) => { for (const key of changes) { const value = currentEnv[key]; const isSecret = key.toLowerCase().includes('apikey') - || key.toLowerCase().includes('secret'); + || key.toLowerCase().includes('secret') + || key === 'httpProxyValues'; if (!value) { console.log(` removed: ${key}`);