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:
@@ -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 />
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
Reference in New Issue
Block a user