mirror of
https://github.com/bestnite/sub2sing-box.git
synced 2026-06-08 16:04:43 +00:00
feat: add custom User-Agent support for subscription and template requests
Add --user-agent / -u CLI flag and user-agent config field to allow customizing the User-Agent header when fetching subscriptions and remote templates. This is useful for providers that require a specific UA to access their subscription links. Closes #23
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
"group-type": "selector",
|
||||
"sort": "name",
|
||||
"sort-type": "asc",
|
||||
"output": "./config.json"
|
||||
"output": "./config.json",
|
||||
"user-agent": "自定义 User-Agent"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ func Convert(c *gin.Context) {
|
||||
data.SortKey,
|
||||
data.SortType,
|
||||
groupRules,
|
||||
data.UserAgent,
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{
|
||||
|
||||
@@ -25,6 +25,7 @@ var (
|
||||
sortType string
|
||||
config string
|
||||
groupRules string
|
||||
userAgent string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -40,6 +41,7 @@ func init() {
|
||||
convertCmd.Flags().StringVarP(&sortType, "sort-type", "T", "", "sort type, asc or desc")
|
||||
convertCmd.Flags().StringVarP(&config, "config", "c", "", "configuration file path")
|
||||
convertCmd.Flags().StringVarP(&groupRules, "group-rules", "R", "", "group rules")
|
||||
convertCmd.Flags().StringVarP(&userAgent, "user-agent", "u", "", "custom User-Agent for fetching subscriptions and remote templates")
|
||||
RootCmd.AddCommand(convertCmd)
|
||||
}
|
||||
|
||||
@@ -71,6 +73,7 @@ func convertRun(cmd *cobra.Command, args []string) {
|
||||
sortKey,
|
||||
sortType,
|
||||
groupRulesMap,
|
||||
userAgent,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println("Conversion error:", err)
|
||||
@@ -152,4 +155,7 @@ func mergeConfig(cfg model.ConvertRequest) {
|
||||
if output == "" {
|
||||
output = cfg.Output
|
||||
}
|
||||
if userAgent == "" {
|
||||
userAgent = cfg.UserAgent
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -36,6 +36,7 @@ func Convert(
|
||||
sortKey string,
|
||||
sortType string,
|
||||
groupRules map[string][]string,
|
||||
userAgent string,
|
||||
) (string, error) {
|
||||
result := ""
|
||||
var err error
|
||||
@@ -44,7 +45,7 @@ func Convert(
|
||||
groupType = C.TypeSelector
|
||||
}
|
||||
|
||||
outbounds, err := ConvertSubscriptionsToSProxy(subscriptions)
|
||||
outbounds, err := ConvertSubscriptionsToSProxy(subscriptions, userAgent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -104,7 +105,7 @@ func Convert(
|
||||
outbounds = AddCountryGroup(outbounds, groupType, sortKey, sortType, groupRules)
|
||||
}
|
||||
if templatePath != "" {
|
||||
templateData, err := ReadTemplate(templatePath)
|
||||
templateData, err := ReadTemplate(templatePath, userAgent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -226,12 +227,12 @@ func AddCountryGroup(proxies []model.Outbound, groupType string, sortKey string,
|
||||
return append(proxies, groups...)
|
||||
}
|
||||
|
||||
func ReadTemplate(template string) (string, error) {
|
||||
func ReadTemplate(template string, userAgent string) (string, error) {
|
||||
var data string
|
||||
var err error
|
||||
isNetworkFile, _ := regexp.MatchString(`^https?://`, template)
|
||||
if isNetworkFile {
|
||||
data, err = util.Fetch(template, 3)
|
||||
data, err = util.Fetch(template, 3, userAgent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -320,10 +321,10 @@ func ConvertCProxyToSProxy(proxy string) (model.Outbound, error) {
|
||||
return model.Outbound{}, errors.New("unknown proxy format")
|
||||
}
|
||||
|
||||
func ConvertSubscriptionsToSProxy(urls []string) ([]model.Outbound, error) {
|
||||
func ConvertSubscriptionsToSProxy(urls []string, userAgent string) ([]model.Outbound, error) {
|
||||
proxyList := make([]model.Outbound, 0)
|
||||
for _, url := range urls {
|
||||
data, err := util.Fetch(url, 3)
|
||||
data, err := util.Fetch(url, 3, userAgent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -12,4 +12,5 @@ type ConvertRequest struct {
|
||||
SortType string `form:"sort-type" json:"sort-type"`
|
||||
Output string `json:"output"`
|
||||
GroupRules string `form:"group-rules" json:"group-rules"`
|
||||
UserAgent string `form:"user-agent" json:"user-agent"`
|
||||
}
|
||||
|
||||
+11
-3
@@ -5,23 +5,31 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Fetch(url string, maxRetryTimes int) (string, error) {
|
||||
func Fetch(url string, maxRetryTimes int, userAgent string) (string, error) {
|
||||
retryTime := 0
|
||||
var err error
|
||||
var resp *http.Response
|
||||
for retryTime < maxRetryTimes {
|
||||
resp, err = http.Get(url)
|
||||
req, reqErr := http.NewRequest("GET", url, nil)
|
||||
if reqErr != nil {
|
||||
return "", reqErr
|
||||
}
|
||||
if userAgent != "" {
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
}
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
retryTime++
|
||||
continue
|
||||
}
|
||||
var data []byte
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
retryTime++
|
||||
continue
|
||||
}
|
||||
return string(data), err
|
||||
return string(data), nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user