diff --git a/docs/public/openapi.json b/docs/public/openapi.json index ce1eabfce..d85a472f7 100644 --- a/docs/public/openapi.json +++ b/docs/public/openapi.json @@ -13569,6 +13569,11 @@ "type": "string", "description": "Prefix for generated outbound tags. Defaults to the lowest free \"sub-\" prefix." }, + "userAgent": { + "type": "string", + "default": "3x-ui-outbound-sub/1.0", + "description": "Custom User-Agent sent when fetching this subscription. Defaults to \"3x-ui-outbound-sub/1.0\"." + }, "updateInterval": { "type": "integer", "default": 600, @@ -13662,6 +13667,11 @@ "type": "string", "description": "Prefix for generated outbound tags. Defaults to the lowest free \"sub-\" prefix." }, + "userAgent": { + "type": "string", + "default": "3x-ui-outbound-sub/1.0", + "description": "Custom User-Agent sent when fetching this subscription. Defaults to \"3x-ui-outbound-sub/1.0\"." + }, "updateInterval": { "type": "integer", "default": 600, @@ -13914,6 +13924,10 @@ "type": "string", "description": "Subscription URL to preview (required)." }, + "userAgent": { + "type": "string", + "description": "Custom User-Agent sent while fetching the preview." + }, "allowPrivate": { "type": "boolean", "description": "Allow a private/internal/loopback URL. Default false." diff --git a/frontend/public/openapi.json b/frontend/public/openapi.json index ce1eabfce..d85a472f7 100644 --- a/frontend/public/openapi.json +++ b/frontend/public/openapi.json @@ -13569,6 +13569,11 @@ "type": "string", "description": "Prefix for generated outbound tags. Defaults to the lowest free \"sub-\" prefix." }, + "userAgent": { + "type": "string", + "default": "3x-ui-outbound-sub/1.0", + "description": "Custom User-Agent sent when fetching this subscription. Defaults to \"3x-ui-outbound-sub/1.0\"." + }, "updateInterval": { "type": "integer", "default": 600, @@ -13662,6 +13667,11 @@ "type": "string", "description": "Prefix for generated outbound tags. Defaults to the lowest free \"sub-\" prefix." }, + "userAgent": { + "type": "string", + "default": "3x-ui-outbound-sub/1.0", + "description": "Custom User-Agent sent when fetching this subscription. Defaults to \"3x-ui-outbound-sub/1.0\"." + }, "updateInterval": { "type": "integer", "default": 600, @@ -13914,6 +13924,10 @@ "type": "string", "description": "Subscription URL to preview (required)." }, + "userAgent": { + "type": "string", + "description": "Custom User-Agent sent while fetching the preview." + }, "allowPrivate": { "type": "boolean", "description": "Allow a private/internal/loopback URL. Default false." diff --git a/frontend/src/pages/api-docs/endpoints.ts b/frontend/src/pages/api-docs/endpoints.ts index 0bda0fe4a..44a5f51c9 100644 --- a/frontend/src/pages/api-docs/endpoints.ts +++ b/frontend/src/pages/api-docs/endpoints.ts @@ -90,6 +90,14 @@ const outboundSubscriptionBodyParams: EndpointParam[] = [ desc: 'Prefix for generated outbound tags. Defaults to the lowest free "sub-" prefix.', optional: true, }, + { + name: 'userAgent', + in: 'body (form)', + type: 'string', + desc: 'Custom User-Agent sent when fetching this subscription. Defaults to "3x-ui-outbound-sub/1.0".', + optional: true, + defaultValue: '3x-ui-outbound-sub/1.0', + }, { name: 'updateInterval', in: 'body (form)', @@ -2502,6 +2510,13 @@ export const sections: readonly Section[] = [ type: 'string', desc: 'Subscription URL to preview (required).', }, + { + name: 'userAgent', + in: 'body (form)', + type: 'string', + desc: 'Custom User-Agent sent while fetching the preview.', + optional: true, + }, { name: 'allowPrivate', in: 'body (form)', diff --git a/frontend/src/pages/xray/outbounds/OutboundsTab.tsx b/frontend/src/pages/xray/outbounds/OutboundsTab.tsx index fd4d2230e..fadadaa62 100644 --- a/frontend/src/pages/xray/outbounds/OutboundsTab.tsx +++ b/frontend/src/pages/xray/outbounds/OutboundsTab.tsx @@ -62,6 +62,8 @@ import { useOutboundColumns } from './useOutboundColumns'; import OutboundCardList from './OutboundCardList'; import SubscriptionOutbounds from './SubscriptionOutbounds'; +const defaultOutboundSubscriptionUserAgent = '3x-ui-outbound-sub/1.0'; + interface OutboundSub { id: number; remark?: string; @@ -69,6 +71,7 @@ interface OutboundSub { enabled?: boolean; allowPrivate?: boolean; allowInsecure?: boolean; + userAgent?: string; prepend?: boolean; priority?: number; tagPrefix?: string; @@ -136,6 +139,7 @@ export default function OutboundsTab({ remark: '', url: '', tagPrefix: '', + userAgent: '', updateInterval: 600, enabled: true, allowPrivate: false, @@ -334,6 +338,7 @@ export default function OutboundsTab({ remark?: string; url?: string; tagPrefix?: string; + userAgent?: string; updateInterval?: number; enabled?: boolean; allowPrivate?: boolean; @@ -344,6 +349,7 @@ export default function OutboundsTab({ remark: src.remark ?? '', url: src.url ?? '', tagPrefix: src.tagPrefix ?? '', + userAgent: src.userAgent ?? '', updateInterval: src.updateInterval ?? 600, enabled: src.enabled ?? true, allowPrivate: src.allowPrivate ?? false, @@ -356,6 +362,7 @@ export default function OutboundsTab({ remark: '', url: '', tagPrefix: '', + userAgent: '', updateInterval: 600, enabled: true, allowPrivate: false, @@ -370,6 +377,7 @@ export default function OutboundsTab({ remark: sub.remark ?? '', url: sub.url ?? '', tagPrefix: sub.tagPrefix ?? '', + userAgent: sub.userAgent ?? '', updateInterval: sub.updateInterval ?? 600, enabled: sub.enabled ?? true, allowPrivate: sub.allowPrivate ?? false, @@ -423,7 +431,12 @@ export default function OutboundsTab({ try { const r = await HttpUtil.post<{ tag?: string; protocol?: string }[]>( '/panel/api/xray/outbound-subs/parse', - { url: newSub.url, allowPrivate: newSub.allowPrivate }, + { + url: newSub.url, + userAgent: newSub.userAgent, + allowPrivate: newSub.allowPrivate, + allowInsecure: newSub.allowInsecure, + }, ); if (r?.success && Array.isArray(r.obj)) { setPreviewData(r.obj); @@ -721,6 +734,13 @@ export default function OutboundsTab({ placeholder={t('pages.xray.outboundSub.tagPrefixPlaceholder')} /> + + setNewSub({ ...newSub, userAgent: e.target.value })} + placeholder={defaultOutboundSubscriptionUserAgent} + /> +