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,
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.",
|
||||
"Nested JSON: source group →": "Nested JSON: source group →",
|
||||
"Network connection failed or server not responding": "Network connection failed or server not responding",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "Network proxy for this channel (supports socks5 protocol)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)",
|
||||
"Never": "Never",
|
||||
"Never expires": "Never expires",
|
||||
"Never used an API Gateway?": "Never used an API Gateway?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "Provider updated successfully",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "Provider-specific endpoint, account, and compatibility settings.",
|
||||
"Proxy Address": "Proxy Address",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host",
|
||||
"Prune Object Items": "Prune Object Items",
|
||||
"Prune object items by conditions": "Prune object items by conditions",
|
||||
"Prune Rule (string or JSON object)": "Prune Rule (string or JSON object)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "JSON imbriqué définissant des règles par groupe pour ajouter (+:), supprimer (-:), ou ajouter des groupes utilisables.",
|
||||
"Nested JSON: source group →": "JSON imbriqué : groupe source →",
|
||||
"Network connection failed or server not responding": "La connexion réseau a échoué ou le serveur ne répond pas",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "Proxy réseau pour ce canal (supporte le protocole socks5)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "Proxy réseau de ce canal (prend en charge HTTP, HTTPS, SOCKS5 et SOCKS5H)",
|
||||
"Never": "Jamais",
|
||||
"Never expires": "N'expire jamais",
|
||||
"Never used an API Gateway?": "Vous n'avez jamais utilisé de passerelle API ?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "Fournisseur mis à jour avec succès",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "Paramètres de point d’accès, de compte et de compatibilité propres au fournisseur.",
|
||||
"Proxy Address": "Adresse du proxy",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "L’adresse du proxy doit utiliser HTTP, HTTPS, SOCKS5 ou SOCKS5H et contenir un hôte valide",
|
||||
"Prune Object Items": "Nettoyer les éléments objet",
|
||||
"Prune object items by conditions": "Nettoyer les éléments d'objets par conditions",
|
||||
"Prune Rule (string or JSON object)": "Règle de nettoyage (chaîne ou objet JSON)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "追加 (+:)、削除 (-:)、または使用可能なグループの追加を行うグループごとのルールを定義するネストされたJSON。",
|
||||
"Nested JSON: source group →": "ネストされたJSON: ソースグループ →",
|
||||
"Network connection failed or server not responding": "ネットワーク接続に失敗したか、サーバーが応答していません",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "このチャネルのネットワークプロキシ (socks5プロトコルをサポート)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "このチャネルのネットワークプロキシ(HTTP、HTTPS、SOCKS5、SOCKS5H に対応)",
|
||||
"Never": "しない",
|
||||
"Never expires": "無期限",
|
||||
"Never used an API Gateway?": "APIゲートウェイを一度も使用したことがありませんか?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "プロバイダーが正常に更新されました",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "プロバイダー固有のエンドポイント、アカウント、互換性設定です。",
|
||||
"Proxy Address": "プロキシアドレス",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "プロキシアドレスは HTTP、HTTPS、SOCKS5、SOCKS5H のいずれかを使用し、有効なホストを含める必要があります",
|
||||
"Prune Object Items": "オブジェクト項目を整理",
|
||||
"Prune object items by conditions": "条件に基づいてオブジェクト項目を削除",
|
||||
"Prune Rule (string or JSON object)": "削除ルール(文字列またはJSONオブジェクト)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "Вложенный JSON, определяющий правила для каждой группы для добавления (+:), удаления (-:) или добавления используемых групп.",
|
||||
"Nested JSON: source group →": "Вложенный JSON: исходная группа →",
|
||||
"Network connection failed or server not responding": "Сбой сетевого подключения или сервер не отвечает",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "Сетевой прокси для этого канала (поддерживает протокол socks5)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "Сетевой прокси для этого канала (поддерживает HTTP, HTTPS, SOCKS5 и SOCKS5H)",
|
||||
"Never": "Никогда",
|
||||
"Never expires": "Никогда не истекает",
|
||||
"Never used an API Gateway?": "Никогда не пользовались API-шлюзом?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "Поставщик успешно обновлен",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "Настройки endpoint, аккаунта и совместимости для конкретного провайдера.",
|
||||
"Proxy Address": "Адрес прокси",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "Адрес прокси должен использовать HTTP, HTTPS, SOCKS5 или SOCKS5H и содержать допустимый узел",
|
||||
"Prune Object Items": "Очистить элементы объекта",
|
||||
"Prune object items by conditions": "Удалить элементы объекта по условиям",
|
||||
"Prune Rule (string or JSON object)": "Правило очистки (строка или JSON-объект)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "JSON lồng nhau xác định quy tắc theo nhóm để thêm (+:), xóa (-:), hoặc nối các nhóm có thể sử dụng.",
|
||||
"Nested JSON: source group →": "JSON lồng nhau: nhóm nguồn →",
|
||||
"Network connection failed or server not responding": "Kết nối mạng thất bại hoặc máy chủ không phản hồi",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "Proxy mạng cho kênh này (hỗ trợ giao thức socks5)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "Proxy mạng cho kênh này (hỗ trợ HTTP, HTTPS, SOCKS5 và SOCKS5H)",
|
||||
"Never": "Không bao giờ",
|
||||
"Never expires": "Không hết hạn",
|
||||
"Never used an API Gateway?": "Chưa bao giờ sử dụng API Gateway?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "Nhà cung cấp đã được cập nhật thành công",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "Thiết lập endpoint, tài khoản và tương thích riêng cho nhà cung cấp.",
|
||||
"Proxy Address": "Địa chỉ Proxy",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "Địa chỉ proxy phải dùng HTTP, HTTPS, SOCKS5 hoặc SOCKS5H và chứa máy chủ hợp lệ",
|
||||
"Prune Object Items": "Dọn mục đối tượng",
|
||||
"Prune object items by conditions": "Dọn dẹp các mục đối tượng theo điều kiện",
|
||||
"Prune Rule (string or JSON object)": "Quy tắc dọn dẹp (chuỗi hoặc đối tượng JSON)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "嵌套 JSON,定義按分組新增(+:)、移除(-:)或追加可用分組的規則。",
|
||||
"Nested JSON: source group →": "嵌套 JSON:源分組 →",
|
||||
"Network connection failed or server not responding": "網絡連接失敗或伺服器未回應",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "此渠道的網絡代理(支援 socks5 協定)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "此渠道的網路代理(支援 HTTP、HTTPS、SOCKS5 和 SOCKS5H)",
|
||||
"Never": "永不",
|
||||
"Never expires": "永不過期",
|
||||
"Never used an API Gateway?": "從未使用過 API 閘道/中轉 API?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "供應商更新成功",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "設定供應商專屬的端點、用戶和兼容性選項。",
|
||||
"Proxy Address": "代理地址",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "代理位址必須使用 HTTP、HTTPS、SOCKS5 或 SOCKS5H,並包含有效的主機",
|
||||
"Prune Object Items": "清理物件項",
|
||||
"Prune object items by conditions": "按條件清理物件中的子項",
|
||||
"Prune Rule (string or JSON object)": "清理規則(字串或 JSON 物件)",
|
||||
|
||||
@@ -2804,7 +2804,7 @@
|
||||
"Nested JSON defining per-group rules for adding (+:), removing (-:), or appending usable groups.": "嵌套 JSON,定义按分组添加(+:)、移除(-:)或追加可用分组的规则。",
|
||||
"Nested JSON: source group →": "嵌套 JSON:源分组 →",
|
||||
"Network connection failed or server not responding": "网络连接失败或服务器未响应",
|
||||
"Network proxy for this channel (supports socks5 protocol)": "此渠道的网络代理(支持 socks5 协议)",
|
||||
"Network proxy for this channel (supports HTTP, HTTPS, SOCKS5, and SOCKS5H)": "此渠道的网络代理(支持 HTTP、HTTPS、SOCKS5 和 SOCKS5H)",
|
||||
"Never": "永不",
|
||||
"Never expires": "永不过期",
|
||||
"Never used an API Gateway?": "从未使用过 API 网关/中转 API?",
|
||||
@@ -3545,6 +3545,7 @@
|
||||
"Provider updated successfully": "提供商更新成功",
|
||||
"Provider-specific endpoint, account, and compatibility settings.": "配置供应商专属的端点、账户和兼容性选项。",
|
||||
"Proxy Address": "代理地址",
|
||||
"Proxy address must use HTTP, HTTPS, SOCKS5, or SOCKS5H and include a valid host": "代理地址必须使用 HTTP、HTTPS、SOCKS5 或 SOCKS5H,并包含有效的主机",
|
||||
"Prune Object Items": "清理对象项",
|
||||
"Prune object items by conditions": "按条件清理对象中的子项",
|
||||
"Prune Rule (string or JSON object)": "清理规则(字符串或 JSON 对象)",
|
||||
|
||||
Reference in New Issue
Block a user