fix(channel): improve proxy client compatibility and cache lifecycle (#6157)

* fix(channel): improve proxy client compatibility and cache lifecycle

* test(controller): use non-fatal assertions for channel tests
This commit is contained in:
yyhhyyyyyy
2026-07-20 18:11:22 +08:00
committed by GitHub
parent 08677566f8
commit e13d4033e5
26 changed files with 537 additions and 147 deletions
@@ -4192,7 +4192,7 @@ export function ChannelMutateDrawer({
</FormControl>
<FormDescription>
{t(
'Network proxy for this channel (supports socks5 protocol)'
'Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)'
)}
</FormDescription>
<FormMessage />
+2
View File
@@ -239,6 +239,8 @@ export const ERROR_MESSAGES = {
REQUIRED_GROUP: 'Group is required',
INVALID_JSON: 'Invalid JSON format',
INVALID_MODEL_MAPPING: 'Invalid model mapping format',
INVALID_PROXY:
'Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host',
CREATE_FAILED: 'Failed to create channel',
UPDATE_FAILED: 'Failed to update channel',
DELETE_FAILED: 'Failed to delete channel',
+37 -2
View File
@@ -37,6 +37,38 @@ import {
// Form Validation Schema
// ============================================================================
const SUPPORTED_PROXY_PROTOCOLS = new Set([
'http:',
'https:',
'socks5:',
'socks5h:',
])
function isOptionalProxyURL(value: string | undefined): boolean {
const trimmedValue = value?.trim() || ''
if (!trimmedValue) return true
const schemeSeparatorIndex = trimmedValue.indexOf('://')
if (schemeSeparatorIndex <= 0) return false
const authorityAndSuffix = trimmedValue.slice(schemeSeparatorIndex + 3)
const suffixIndex = authorityAndSuffix.search(/[/?#]/)
if (suffixIndex >= 0 && authorityAndSuffix.slice(suffixIndex) !== '/') {
return false
}
try {
const parsedURL = new URL(trimmedValue)
return (
SUPPORTED_PROXY_PROTOCOLS.has(parsedURL.protocol) &&
Boolean(parsedURL.hostname) &&
parsedURL.port !== '0'
)
} catch {
return false
}
}
function parseOptionalJson(value: string | undefined): unknown {
if (!value?.trim()) return undefined
return JSON.parse(value)
@@ -188,7 +220,10 @@ export const channelFormSchema = z
// Channel extra settings (stored in setting JSON, not sent directly)
force_format: z.boolean().optional(),
thinking_to_content: z.boolean().optional(),
proxy: z.string().optional(),
proxy: z
.string()
.optional()
.refine(isOptionalProxyURL, ERROR_MESSAGES.INVALID_PROXY),
pass_through_body_enabled: z.boolean().optional(),
system_prompt: z.string().optional(),
system_prompt_override: z.boolean().optional(),
@@ -505,7 +540,7 @@ function buildSettingJSON(formData: ChannelFormValues): string {
const settingObj = {
force_format: formData.force_format || false,
thinking_to_content: formData.thinking_to_content || false,
proxy: formData.proxy || '',
proxy: formData.proxy?.trim() || '',
pass_through_body_enabled: formData.pass_through_body_enabled || false,
system_prompt: formData.system_prompt || '',
system_prompt_override: formData.system_prompt_override || false,