mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-17 15:47:14 +00:00
feat(sub): add Happ client integration, routing presets, and app management (#6434)
* feat(sub): add Happ client integration, routing presets, and app management Implement comprehensive Happ proxy client integration according to official developer specifications. - Fix header emission on disabled routing and hidden settings to send explicit '0' headers rather than omitting, allowing Happ clients to reset cached settings. - Add support for 'happ://routing/off' deeplink in routing validation. - Preserve '?serverDescription=' query parameters in link fragments without escaping to support Happ server subtitles across VMess, VLESS, Trojan and SS. - Add Happ application management headers: ProviderID, New-Url, Fallback-Url, Sub-Info banners, Sub-Expire notifications, No-Limit mode, hardware ID enforcement, TUN modes/types, route exclusions, APNS exclusions, and per-app proxy settings. - Add curated routing presets (Iran Bypass, China Direct, AdBlock, Global) and interactive visual rule generator in frontend settings. - Synchronize all 13 translation locales with native Persian, Russian, and Chinese translations. * fix(sub): keep Happ header overrides behind the auto-detect opt-in The Routing-Enable/Hide-Settings off values were emitted on the User-Agent alone, so every panel that upgraded would push "Routing-Enable: 0" — documented by happ.su as disabling routing globally — to every Happ client without the operator enabling anything. They now ride subHappAutoDetect like every other Happ header. Two further mismatches against the vendor spec: - serverDescription was written as a key of the VMess base64 JSON object. happ.su documents it as a "#Title?serverDescription=<base64>" link parameter or a JSON "meta" entry, so the caption never reached Happ while every other VMess consumer received an unknown key. Dropped rather than moved: emitting the documented form is unsafe here because our own parser base64-decodes the whole VMess body (internal/util/link/outbound.go). - The TUN Mode dropdown stored the literal "default", forwarded as "Tun-Mode: default", where happ.su documents system|gvisor only. It now stores the unset value so no header is sent. TUN Type "default" is a documented value and is unchanged. Each fix carries a test that fails without it.
This commit is contained in:
@@ -215,6 +215,31 @@ func (s *Server) initRouter() (*gin.Engine, error) {
|
||||
SubIncyRoutingRules = ""
|
||||
}
|
||||
|
||||
happCfg := HappConfig{}
|
||||
happCfg.AutoDetect, _ = s.settingService.GetSubHappAutoDetect()
|
||||
happCfg.ProviderId, _ = s.settingService.GetSubHappProviderId()
|
||||
happCfg.NewUrl, _ = s.settingService.GetSubHappNewUrl()
|
||||
happCfg.FallbackUrl, _ = s.settingService.GetSubHappFallbackUrl()
|
||||
happCfg.SubInfoColor, _ = s.settingService.GetSubHappSubInfoColor()
|
||||
happCfg.SubInfoText, _ = s.settingService.GetSubHappSubInfoText()
|
||||
happCfg.SubInfoButtonText, _ = s.settingService.GetSubHappSubInfoButtonText()
|
||||
happCfg.SubInfoButtonLink, _ = s.settingService.GetSubHappSubInfoButtonLink()
|
||||
happCfg.SubExpire, _ = s.settingService.GetSubHappSubExpire()
|
||||
happCfg.SubExpireButtonLink, _ = s.settingService.GetSubHappSubExpireButtonLink()
|
||||
happCfg.NotificationExpire, _ = s.settingService.GetSubHappNotificationExpire()
|
||||
happCfg.NoLimit, _ = s.settingService.GetSubHappNoLimit()
|
||||
happCfg.AlwaysHwid, _ = s.settingService.GetSubHappAlwaysHwid()
|
||||
happCfg.TunMode, _ = s.settingService.GetSubHappTunMode()
|
||||
happCfg.TunType, _ = s.settingService.GetSubHappTunType()
|
||||
happCfg.ExcludeRoutes, _ = s.settingService.GetSubHappExcludeRoutes()
|
||||
happCfg.ExcludeApns, _ = s.settingService.GetSubHappExcludeApns()
|
||||
happCfg.ColorProfile, _ = s.settingService.GetSubHappColorProfile()
|
||||
happCfg.PingType, _ = s.settingService.GetSubHappPingType()
|
||||
happCfg.AutoConnect, _ = s.settingService.GetSubHappAutoConnect()
|
||||
happCfg.AutoConnectType, _ = s.settingService.GetSubHappAutoConnectType()
|
||||
happCfg.PerAppMode, _ = s.settingService.GetSubHappPerAppMode()
|
||||
happCfg.PerAppList, _ = s.settingService.GetSubHappPerAppList()
|
||||
|
||||
// set per-request localizer from headers/cookies
|
||||
engine.Use(locale.LocalizerMiddleware())
|
||||
|
||||
@@ -296,6 +321,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
|
||||
WithSUBEnableRouting(SubEnableRouting),
|
||||
WithSUBRoutingRules(SubRoutingRules),
|
||||
WithSUBHideSettings(SubHideSettings),
|
||||
WithSUBHappConfig(happCfg),
|
||||
WithSUBIncyEnableRouting(SubIncyEnableRouting),
|
||||
WithSUBIncyRoutingRules(SubIncyRoutingRules),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user