feat(outbounds): support custom subscription user agents (#6398)

Some subscription providers require a client-specific User-Agent before returning outbound links. Persist an optional value per subscription and use it for refreshes and previews while preserving the existing default for blank values.
This commit is contained in:
Timur Chernykh
2026-09-11 16:32:04 +03:00
committed by GitHub
parent 89ee1242bd
commit 9f07951ba7
22 changed files with 134 additions and 9 deletions
+6 -3
View File
@@ -516,6 +516,7 @@ func (a *XraySettingController) createOutboundSub(c *gin.Context) {
remark := c.PostForm("remark")
rawURL := c.PostForm("url")
prefix := c.PostForm("tagPrefix")
userAgent := c.PostForm("userAgent")
enabled := c.PostForm("enabled") != "false"
allowPrivate := c.PostForm("allowPrivate") == "true"
allowInsecure := c.PostForm("allowInsecure") == "true"
@@ -527,7 +528,7 @@ func (a *XraySettingController) createOutboundSub(c *gin.Context) {
interval = v
}
}
sub, err := a.OutboundSubscriptionService.Create(remark, rawURL, prefix, enabled, interval, allowPrivate, prepend, allowInsecure)
sub, err := a.OutboundSubscriptionService.Create(remark, rawURL, prefix, userAgent, enabled, interval, allowPrivate, prepend, allowInsecure)
if err != nil {
jsonMsg(c, "Failed to create outbound subscription", err)
return
@@ -545,6 +546,7 @@ func (a *XraySettingController) updateOutboundSub(c *gin.Context) {
remark := c.PostForm("remark")
rawURL := c.PostForm("url")
prefix := c.PostForm("tagPrefix")
userAgent := c.PostForm("userAgent")
enabled := c.PostForm("enabled") != "false"
allowPrivate := c.PostForm("allowPrivate") == "true"
allowInsecure := c.PostForm("allowInsecure") == "true"
@@ -556,7 +558,7 @@ func (a *XraySettingController) updateOutboundSub(c *gin.Context) {
interval = v
}
}
if err := a.OutboundSubscriptionService.Update(subID, remark, rawURL, prefix, enabled, interval, allowPrivate, prepend, allowInsecure); err != nil {
if err := a.OutboundSubscriptionService.Update(subID, remark, rawURL, prefix, userAgent, enabled, interval, allowPrivate, prepend, allowInsecure); err != nil {
jsonMsg(c, "Failed to update outbound subscription", err)
return
}
@@ -624,12 +626,13 @@ func (a *XraySettingController) parseOutboundSubURL(c *gin.Context) {
}
allowPrivate := c.PostForm("allowPrivate") == "true"
allowInsecure := c.PostForm("allowInsecure") == "true"
userAgent := c.PostForm("userAgent")
// Use a throw-away service instance; it only needs the settingService for proxy.
svc := service.OutboundSubscriptionService{}
// We don't have a direct "fetch once" that returns without storing, so we
// temporarily create a disabled row, refresh it, then delete. Cleaner would
// be to expose a pure ParseURL on the service, but this keeps the surface small.
tmp, err := svc.Create("preview", rawURL, "", false, 600, allowPrivate, false, allowInsecure)
tmp, err := svc.Create("preview", rawURL, "", userAgent, false, 600, allowPrivate, false, allowInsecure)
if err != nil {
jsonMsg(c, "Failed to preview subscription", err)
return