Skip to content

feat: apply proxy settings to Electron, Python, and child processes#1679

Open
snomiao wants to merge 8 commits into
mainfrom
sno-proxysettings
Open

feat: apply proxy settings to Electron, Python, and child processes#1679
snomiao wants to merge 8 commits into
mainfrom
sno-proxysettings

Conversation

@snomiao
Copy link
Copy Markdown

@snomiao snomiao commented Mar 26, 2026

Summary

  • Read Comfy.Network.Proxy.* settings from comfy.settings.json on app startup
  • Configure Chromium via session.defaultSession.setProxy() for Electron's own network
  • Set process.env HTTP_PROXY/HTTPS_PROXY/NO_PROXY for all child processes
  • Inject --http-proxy/--https-proxy/--no-proxy into Python server launch args
  • Forward proxy env vars to uv PTY sessions for pip/package installs

Part of a cross-repo feature. Related PRs:

  • Comfy-Org/ComfyUI — backend CLI args + env var setup
  • Comfy-Org/ComfyUI_frontend — proxy settings UI

Ref: #1105

Test plan

  • Set proxy URL in Settings > Comfy > Network, restart app
  • Verify Python server receives --http-proxy arg
  • Verify Electron BrowserWindow routes through proxy
  • Verify uv/pip operations use proxy during package installs
  • No proxy configured = no behavior change

🤖 Generated with Claude Code

┆Issue is synchronized with this Notion page by Unito

Summary by CodeRabbit

  • New Features

    • Added network proxy support: users can configure HTTP proxy, HTTPS proxy, and proxy bypass rules; these are applied at app startup, affect the embedded browser/networking, server launch, and child processes.
  • Chores

    • Extended settings schema to include proxy configuration keys with default empty values.
  • Tests

    • Updated unit tests and fixtures to include the new proxy settings.

Read Comfy.Network.Proxy.* settings from comfy.settings.json on startup:
- Configure Chromium via session.defaultSession.setProxy()
- Set process.env HTTP_PROXY/HTTPS_PROXY/NO_PROXY for child processes
- Inject --http-proxy/--https-proxy/--no-proxy into Python server args
- Forward proxy env vars to uv PTY sessions for pip/package installs

Ref: #1105

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 53b25330-7daa-4b77-806f-f96183996f6d

📥 Commits

Reviewing files that changed from the base of the PR and between 4a2ead9 and a8099f0.

📒 Files selected for processing (3)
  • src/main-process/comfyDesktopApp.ts
  • src/main.ts
  • tests/unit/main-process/comfyDesktopApp.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main-process/comfyDesktopApp.ts
  • src/main.ts

📝 Walkthrough

Walkthrough

The pull request adds three proxy settings to the configuration schema and propagates them to startup proxy application (Electron/Chromium), server CLI launch arguments, and virtual environment child-process environments.

Changes

Cohort / File(s) Summary
Configuration Schema
src/config/comfySettings.ts, tests/unit/config/comfySettings.test.ts
Added Comfy.Network.Proxy.HttpUrl, Comfy.Network.Proxy.HttpsUrl, and Comfy.Network.Proxy.NoProxy to DEFAULT_SETTINGS and ComfySettingsData; test fixture updated with the keys (empty strings).
Proxy Application at Startup
src/main.ts
New applyProxySettings logic reads proxy keys, redacts credentials for logs, calls session.defaultSession.setProxy() with constructed rules, sets HTTP_PROXY/HTTPS_PROXY/NO_PROXY env vars, and downgrades failures to warnings.
Server Launch Configuration
src/main-process/comfyDesktopApp.ts, tests/unit/main-process/comfyDesktopApp.test.ts
buildServerArgs now reads settings and conditionally injects --http-proxy, --https-proxy, and --no-proxy CLI args when values are non-empty; test mocks adjusted to return empty strings for proxy keys.
Virtual Environment Setup
src/virtualEnvironment.ts
VirtualEnvironment.uvEnv now conditionally re-exports HTTP_PROXY, HTTPS_PROXY, and NO_PROXY from process.env into the environment passed to uv.

Sequence Diagram

sequenceDiagram
    actor App as Application Startup
    participant Cfg as Config<br/>(comfySettings)
    participant ElectronSession as Electron Session<br/>(main.ts)
    participant ServerBuild as Server Builder<br/>(comfyDesktopApp)
    participant UVEnv as Virtual Env<br/>(virtualEnvironment)
    participant ServerProc as Server Process

    App->>Cfg: Load proxy settings (HttpUrl, HttpsUrl, NoProxy)
    Cfg-->>App: Return proxy config

    App->>ElectronSession: applyProxySettings()
    ElectronSession->>ElectronSession: Build Chromium proxy rules
    ElectronSession->>ElectronSession: session.defaultSession.setProxy()
    ElectronSession->>App: Set env vars (HTTP/HTTPS/NO_PROXY)

    App->>ServerBuild: buildServerArgs()
    ServerBuild->>Cfg: Read proxy settings
    Cfg-->>ServerBuild: Return proxy config
    ServerBuild->>ServerBuild: Inject --http-proxy / --https-proxy / --no-proxy

    App->>UVEnv: Initialize uv environment
    UVEnv->>UVEnv: Re-export HTTP_PROXY, HTTPS_PROXY, NO_PROXY
    UVEnv-->>App: Env for child processes

    App->>ServerProc: Launch server with CLI args & env
    ServerProc-->>ServerProc: Uses proxies for network requests
Loading

Poem

🐰 Three little proxies, hop through the code,
HTTP and HTTPS on the network road,
From config to Electron, environment too,
Settings flow neatly with NoProxy cue,
A rabbit's cheer—connections routed true!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and accurately summarizes the main change: adding proxy settings support across Electron, Python, and child processes, which is the core focus of all modifications in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sno-proxysettings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 6/8 reviews remaining, refill in 14 minutes and 41 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

snomiao and others added 4 commits March 29, 2026 04:19
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… proxies

- Redact embedded credentials from proxy URLs before logging to prevent
  secrets from leaking into log files and Sentry crash reports.
- Build proper Chromium per-scheme proxy rules ("http=X;https=Y") when
  both HTTP and HTTPS proxies are configured, instead of collapsing them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@snomiao snomiao marked this pull request as ready for review March 31, 2026 09:16
@snomiao snomiao requested review from a team as code owners March 31, 2026 09:16
Copilot AI review requested due to automatic review settings March 31, 2026 09:16
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request labels Mar 31, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for configuring proxy behavior across the desktop app by reading Comfy.Network.Proxy.* from comfy.settings.json at startup and propagating the settings into Electron networking and spawned processes.

Changes:

  • Load proxy settings on app startup and apply them to Electron (session.defaultSession.setProxy) and process.env.
  • Pass proxy options through to the Python server via CLI args.
  • Ensure proxy env vars are available to uv PTY sessions, and extend settings defaults/tests for new keys.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/main.ts Loads settings at startup and applies proxy config to Electron + environment variables.
src/main-process/comfyDesktopApp.ts Injects proxy settings into ComfyUI server launch arguments.
src/virtualEnvironment.ts Re-exports proxy env vars into PTY environment setup.
src/config/comfySettings.ts Adds default settings + typings for proxy keys.
tests/unit/config/comfySettings.test.ts Extends settings fixtures to include proxy keys.
tests/unit/main-process/comfyDesktopApp.test.ts Updates settings mocks to account for new proxy keys.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main.ts
Comment on lines +134 to +152
const httpProxy = settings.get('Comfy.Network.Proxy.HttpUrl');
const httpsProxy = settings.get('Comfy.Network.Proxy.HttpsUrl');
const noProxy = settings.get('Comfy.Network.Proxy.NoProxy');

if (!httpProxy && !httpsProxy) return;

log.info(
`Applying proxy settings: HTTP=${redactProxyUrl(httpProxy) || '(none)'}, HTTPS=${redactProxyUrl(httpsProxy) || '(none)'}`
);

// Build Chromium proxy rules that respect separate HTTP/HTTPS proxies.
// Format: "http=<proxy>;https=<proxy>" or a single proxy for both.
const proxyRules = buildChromiumProxyRules(httpProxy, httpsProxy);

// Configure Chromium's network stack (affects Electron's own requests and BrowserWindow).
await session.defaultSession.setProxy({
proxyRules,
proxyBypassRules: noProxy || undefined,
});
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applyProxySettings returns early when both httpProxy and httpsProxy are empty, which also prevents applying NO_PROXY/no_proxy and proxyBypassRules. This means a user cannot configure only bypass rules (e.g., to complement an OS- or externally-provided proxy). Consider applying NO_PROXY and proxyBypassRules whenever noProxy is set, even if no explicit proxy URL is configured.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in d14addf: moved NO_PROXY/no_proxy export before the early return so a noProxy-only config is applied even when no explicit proxy URL is configured.

Comment thread src/main.ts
Comment on lines +177 to +192
* Builds Chromium-format proxy rules from separate HTTP and HTTPS proxy URLs.
* When both are set, uses per-scheme syntax: "http=<proxy>;https=<proxy>".
* When only one is set, uses it as a catch-all.
*/
function buildChromiumProxyRules(httpProxy: string, httpsProxy: string): string {
if (httpProxy && httpsProxy) {
return `http=${httpProxy};https=${httpsProxy}`;
}
return httpProxy || httpsProxy;
}

/**
* Redacts embedded credentials from a proxy URL for safe logging.
* E.g. "http://user:pass@host:8080" becomes "http://***@host:8080".
*/
function redactProxyUrl(url: string): string {
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildChromiumProxyRules injects the values from Comfy.Network.Proxy.*Url directly into Chromium proxy rules (e.g. http=${httpProxy}), but these settings are named/treated as URLs elsewhere (env vars, redaction with new URL()). Chromium/Electron proxyRules typically expects host:port (or username:password@host:port) rather than a full URL; producing http=http://host:port is likely to be rejected. Consider normalizing the configured URL(s) into Chromium's expected proxy rule format before calling session.defaultSession.setProxy().

Suggested change
* Builds Chromium-format proxy rules from separate HTTP and HTTPS proxy URLs.
* When both are set, uses per-scheme syntax: "http=<proxy>;https=<proxy>".
* When only one is set, uses it as a catch-all.
*/
function buildChromiumProxyRules(httpProxy: string, httpsProxy: string): string {
if (httpProxy && httpsProxy) {
return `http=${httpProxy};https=${httpsProxy}`;
}
return httpProxy || httpsProxy;
}
/**
* Redacts embedded credentials from a proxy URL for safe logging.
* E.g. "http://user:pass@host:8080" becomes "http://***@host:8080".
*/
function redactProxyUrl(url: string): string {
* Normalizes a proxy URL into Chromium `proxyRules` token format.
* Input is expected to be a full URL (e.g. "http://user:pass@host:8080").
* Output is "user:pass@host:port" or "host:port" (no scheme), which is what
* Electron/Chromium expects in `proxyRules`.
*/
function normalizeProxyUrlForChromium(proxyUrl?: string): string | undefined {
if (!proxyUrl) return undefined;
try {
const parsed = new URL(proxyUrl);
const auth =
parsed.username !== ''
? `${parsed.username}${parsed.password !== '' ? `:${parsed.password}` : ''}@`
: '';
const host = parsed.hostname;
const port = parsed.port;
const hostPort = port ? `${host}:${port}` : host;
if (!hostPort) {
// If hostname is missing, fall back to the original string.
return proxyUrl;
}
return `${auth}${hostPort}`;
} catch {
// On parse failure, fall back to the original string so we don't
// accidentally disable proxying entirely.
return proxyUrl;
}
}
/**
* Builds Chromium-format proxy rules from separate HTTP and HTTPS proxy URLs.
* When both are set, uses per-scheme syntax: "http=<proxy>;https=<proxy>".
* When only one is set, uses it as a catch-all.
*/
function buildChromiumProxyRules(httpProxy: string | undefined, httpsProxy: string | undefined): string {
const normalizedHttp = normalizeProxyUrlForChromium(httpProxy);
const normalizedHttps = normalizeProxyUrlForChromium(httpsProxy);
if (normalizedHttp && normalizedHttps) {
return `http=${normalizedHttp};https=${normalizedHttps}`;
}
// If only one proxy is defined, use it as a catch-all.
return normalizedHttp || normalizedHttps || '';
}
/**
* Redacts embedded credentials from a proxy URL for safe logging.
* E.g. "http://user:pass@host:8080" becomes "http://***@host:8080".
*/
function redactProxyUrl(url?: string): string {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in d14addf: for single-proxy cases, buildChromiumProxyRules now adds the appropriate scheme prefix (http= or https=) so the proxy is only applied to the intended scheme. Chromium's ProxyConfig grammar accepts full URLs as the server value (e.g. https=http://proxy:8080), so the scheme prefix is the key correction here rather than URL normalization.

Comment on lines 46 to +63
async buildServerArgs({ useExternalServer, COMFY_HOST, COMFY_PORT }: DevOverrides): Promise<ServerArgs> {
// Shallow-clone the setting launch args to avoid mutation.
const serverArgs: ServerArgs = {
...DEFAULT_SERVER_ARGS,
...useComfySettings().get('Comfy.Server.LaunchArgs'),
};

if (COMFY_HOST) serverArgs.listen = COMFY_HOST;
if (COMFY_PORT) serverArgs.port = COMFY_PORT;

// Inject proxy settings from frontend config into server CLI args.
const settings = useComfySettings();
const httpProxy = settings.get('Comfy.Network.Proxy.HttpUrl');
const httpsProxy = settings.get('Comfy.Network.Proxy.HttpsUrl');
const noProxy = settings.get('Comfy.Network.Proxy.NoProxy');
if (httpProxy) serverArgs['http-proxy'] = httpProxy;
if (httpsProxy) serverArgs['https-proxy'] = httpsProxy;
if (noProxy) serverArgs['no-proxy'] = noProxy;
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildServerArgs calls useComfySettings() twice in the same method (once for Comfy.Server.LaunchArgs and again for proxy keys). Since this is a singleton accessor, it’s simpler to call it once and reuse the same instance to avoid duplicated lookups and keep the args-building logic easier to follow.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 2298c45: useComfySettings() is now called once at the top of buildServerArgs and the instance reused throughout.

get: vi.fn(() => true),
get: vi.fn((key: string) => {
// Proxy settings should default to empty string (no proxy configured).
if (key.startsWith('Comfy.Network.Proxy.')) return '';
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mocked ComfySettings.get returns true for all non-proxy keys. This works in current tests but is type-inaccurate for keys used as objects (e.g. Comfy.Server.LaunchArgs) and can mask real issues if future tests start asserting on these values. Consider returning more realistic defaults per key (at least {} for Comfy.Server.LaunchArgs) while keeping proxy keys as empty strings.

Suggested change
if (key.startsWith('Comfy.Network.Proxy.')) return '';
if (key.startsWith('Comfy.Network.Proxy.')) return '';
// Server launch arguments are expected to be an object.
if (key === 'Comfy.Server.LaunchArgs') return {};
// Default to a truthy value for other keys.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a8099f0: the mock now returns true for Comfy-Desktop.AutoUpdate, {} for Comfy.Server.LaunchArgs, '' for proxy keys, and undefined as the catch-all fallback.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main-process/comfyDesktopApp.ts`:
- Around line 58-63: The proxy string values (httpProxy, httpsProxy, noProxy)
are not normalized and whitespace-only values slip past the truthy checks and
end up in serverArgs; trim each value (e.g., normalize httpProxy, httpsProxy,
noProxy via .trim() when they are strings) and only assign to
serverArgs['http-proxy'], ['https-proxy'], ['no-proxy'] if the trimmed result is
non-empty, ensuring you handle non-string/undefined safely and preserve existing
keys otherwise.

In `@src/main.ts`:
- Around line 138-139: The early return when both httpProxy and httpsProxy are
empty causes NO_PROXY/no_proxy (and Comfy.Network.Proxy.NoProxy-only configs) to
be skipped; modify the logic in the proxy setup so that exporting
NO_PROXY/no_proxy and handling Comfy.Network.Proxy.NoProxy happens before any
return or ensure those exports run unconditionally (move the NO_PROXY/no_proxy
export code out of the httpProxy/httpsProxy conditional or call it regardless),
update the proxy initialization in the same way for the similar block around the
code referenced (the second block handling httpProxy/httpsProxy) to ensure
NoProxy is not dropped.
- Around line 181-186: buildChromiumProxyRules currently returns a raw proxy URL
for single-proxy cases which causes Electron to treat it as a catch-all; update
the function so when only httpProxy is present it returns "http=<httpProxy>" and
when only httpsProxy is present it returns "https=<httpsProxy>", keeping the
existing combined "http=<httpProxy>;https=<httpsProxy>" when both are set and
returning an empty string/undefined when neither is provided; change references
in the function signature buildChromiumProxyRules(httpProxy, httpsProxy)
accordingly.

In `@tests/unit/main-process/comfyDesktopApp.test.ts`:
- Around line 18-22: The mock for settings.get (vi.fn in
comfyDesktopApp.test.ts) is too broad — it returns '' for proxy keys but true
for everything else which makes values like "Comfy.Server.LaunchArgs"
unrealistic and can hide regressions; update the mock to return realistic,
specific values per key (e.g., return an empty array or the expected launch-args
structure for "Comfy.Server.LaunchArgs", booleans for feature flags, numbers for
numeric keys, etc.) and only default to a safe fallback (null or undefined) when
a key is truly unknown; locate the vi.fn mock in the test, and adjust cases to
explicitly handle "Comfy.Server.LaunchArgs" and any other keys used by
buildServerArgs so the test exercises real shapes rather than a blanket true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f755018c-8305-4461-9c71-c75696c79a15

📥 Commits

Reviewing files that changed from the base of the PR and between f0b53f0 and 4a2ead9.

📒 Files selected for processing (6)
  • src/config/comfySettings.ts
  • src/main-process/comfyDesktopApp.ts
  • src/main.ts
  • src/virtualEnvironment.ts
  • tests/unit/config/comfySettings.test.ts
  • tests/unit/main-process/comfyDesktopApp.test.ts

Comment thread src/main-process/comfyDesktopApp.ts Outdated
Comment thread src/main.ts
Comment thread src/main.ts
Comment thread tests/unit/main-process/comfyDesktopApp.test.ts
@snomiao snomiao requested a review from christian-byrne April 28, 2026 23:45
snomiao and others added 3 commits April 29, 2026 08:52
…x in proxy rules

- Move NO_PROXY/no_proxy export before the early return so a noProxy-only
  config is honoured even when no explicit proxy URL is set
- Fix buildChromiumProxyRules to use scheme-specific prefixes (http=/https=)
  for single-proxy cases, preventing unintended catch-all behaviour when
  only one scheme's proxy is configured

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ildServerArgs

- Call useComfySettings() once and reuse the instance to avoid duplicated
  singleton lookups
- Trim proxy string values before truthy checks so whitespace-only inputs
  do not emit invalid server CLI args

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Return specific values per key so the mock accurately reflects real types:
- true for Comfy-Desktop.AutoUpdate (boolean)
- {} for Comfy.Server.LaunchArgs (object)
- '' for proxy keys (string)
- undefined as the catch-all fallback

This prevents type-inaccurate returns from masking future regressions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants