[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
142
domain/httpNetworkProxy.ts
Normal file
142
domain/httpNetworkProxy.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* App-level HTTP(S) network proxy settings.
|
||||
*
|
||||
* Distinct from SSH ProxyJump / ProxyCommand profiles in the vault.
|
||||
* Used by cloud sync (Google Drive / OneDrive / GitHub / WebDAV / S3),
|
||||
* AI provider fetches, and other Chromium/Node outbound HTTPS traffic.
|
||||
*/
|
||||
|
||||
export type HttpNetworkProxyMode = 'system' | 'direct' | 'custom';
|
||||
|
||||
export interface HttpNetworkProxySettings {
|
||||
mode: HttpNetworkProxyMode;
|
||||
/** Custom proxy URL, e.g. http://127.0.0.1:7890 or socks5://127.0.0.1:1080 */
|
||||
url: string;
|
||||
/** Comma-separated bypass hosts; Chromium also accepts `<local>`. */
|
||||
bypass: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_HTTP_NETWORK_PROXY: HttpNetworkProxySettings = {
|
||||
mode: 'system',
|
||||
url: '',
|
||||
bypass: '<local>',
|
||||
};
|
||||
|
||||
const VALID_MODES = new Set<HttpNetworkProxyMode>(['system', 'direct', 'custom']);
|
||||
|
||||
function asTrimmedString(value: unknown): string {
|
||||
return typeof value === 'string' ? value.trim() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip userinfo from proxy URLs without rewriting the rest of the string.
|
||||
* Electron `proxyRules` does not support credentials, and we must not persist
|
||||
* proxy passwords in localStorage. Avoid `new URL()` round-trips so incomplete
|
||||
* drafts like `http://127.0.0.1:` keep the trailing colon while the user types
|
||||
* a port.
|
||||
*/
|
||||
export function sanitizeProxyUrl(proxyUrl: string): string {
|
||||
const trimmed = asTrimmedString(proxyUrl);
|
||||
if (!trimmed) return '';
|
||||
// Strip userinfo for both scheme URLs (`http://user:pass@host`) and
|
||||
// scheme-less drafts (`user:pass@host:8080`). Electron proxyRules does not
|
||||
// support credentials and we must not persist proxy passwords.
|
||||
return trimmed.replace(/^([a-z][a-z0-9+.-]*:\/\/)?([^/?#]*@)/i, '$1');
|
||||
}
|
||||
|
||||
export function normalizeHttpNetworkProxySettings(
|
||||
raw: unknown,
|
||||
): HttpNetworkProxySettings {
|
||||
if (!raw || typeof raw !== 'object') {
|
||||
return { ...DEFAULT_HTTP_NETWORK_PROXY };
|
||||
}
|
||||
|
||||
const record = raw as Record<string, unknown>;
|
||||
const modeRaw = asTrimmedString(record.mode);
|
||||
const mode: HttpNetworkProxyMode = VALID_MODES.has(modeRaw as HttpNetworkProxyMode)
|
||||
? (modeRaw as HttpNetworkProxyMode)
|
||||
: 'system';
|
||||
const url = sanitizeProxyUrl(asTrimmedString(record.url));
|
||||
const bypass = asTrimmedString(record.bypass) || DEFAULT_HTTP_NETWORK_PROXY.bypass;
|
||||
|
||||
if (mode === 'system') {
|
||||
return { mode: 'system', url: '', bypass: DEFAULT_HTTP_NETWORK_PROXY.bypass };
|
||||
}
|
||||
|
||||
if (mode === 'direct') {
|
||||
return { mode: 'direct', url: '', bypass: DEFAULT_HTTP_NETWORK_PROXY.bypass };
|
||||
}
|
||||
|
||||
// Allow custom mode with an empty URL so the settings UI can show the
|
||||
// URL field before the user has typed anything. Electron apply paths
|
||||
// treat empty custom as system until a URL is present.
|
||||
return { mode: 'custom', url, bypass };
|
||||
}
|
||||
|
||||
export function areHttpNetworkProxySettingsEqual(
|
||||
a: HttpNetworkProxySettings,
|
||||
b: HttpNetworkProxySettings,
|
||||
): boolean {
|
||||
return a.mode === b.mode && a.url === b.url && a.bypass === b.bypass;
|
||||
}
|
||||
|
||||
/** Payload for Electron `session.setProxy`. */
|
||||
export function buildElectronProxyConfig(
|
||||
settings: HttpNetworkProxySettings,
|
||||
): { mode: 'system' } | { mode: 'direct' } | {
|
||||
mode: 'fixed_servers';
|
||||
proxyRules: string;
|
||||
proxyBypassRules: string;
|
||||
} {
|
||||
if (settings.mode === 'direct') return { mode: 'direct' };
|
||||
if (settings.mode === 'custom') {
|
||||
return {
|
||||
mode: 'fixed_servers',
|
||||
proxyRules: settings.url,
|
||||
proxyBypassRules: settings.bypass || DEFAULT_HTTP_NETWORK_PROXY.bypass,
|
||||
};
|
||||
}
|
||||
return { mode: 'system' };
|
||||
}
|
||||
|
||||
export type NodeProxyEnv = {
|
||||
HTTP_PROXY: string;
|
||||
HTTPS_PROXY: string;
|
||||
NO_PROXY: string;
|
||||
http_proxy: string;
|
||||
https_proxy: string;
|
||||
no_proxy: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Env vars for Node `http`/`https`/`webdav`/`aws-sdk` stacks that honor
|
||||
* HTTP(S)_PROXY. Returns `null` for system mode so callers leave process.env
|
||||
* alone (Chromium `net.fetch` still uses OS proxy via session.setProxy).
|
||||
*/
|
||||
export function buildNodeProxyEnv(
|
||||
settings: HttpNetworkProxySettings,
|
||||
): NodeProxyEnv | null {
|
||||
if (settings.mode === 'system') return null;
|
||||
|
||||
if (settings.mode === 'direct') {
|
||||
return {
|
||||
HTTP_PROXY: '',
|
||||
HTTPS_PROXY: '',
|
||||
NO_PROXY: '',
|
||||
http_proxy: '',
|
||||
https_proxy: '',
|
||||
no_proxy: '',
|
||||
};
|
||||
}
|
||||
|
||||
const url = settings.url;
|
||||
const bypass = settings.bypass || '';
|
||||
return {
|
||||
HTTP_PROXY: url,
|
||||
HTTPS_PROXY: url,
|
||||
NO_PROXY: bypass,
|
||||
http_proxy: url,
|
||||
https_proxy: url,
|
||||
no_proxy: bypass,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user