From af1bfe4e3eed9a00bbba55b891c22afee93773b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 1 May 2025 11:00:01 +0800 Subject: [PATCH] Make `rule_set.format` optional --- cmd/sing-box/cmd_rule_set_match.go | 9 +++++ docs/configuration/rule-set/index.md | 2 ++ docs/configuration/rule-set/index.zh.md | 2 ++ option/rule_set.go | 44 ++++++++++++++++++++++--- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/cmd/sing-box/cmd_rule_set_match.go b/cmd/sing-box/cmd_rule_set_match.go index f5016117..e3dc19b8 100644 --- a/cmd/sing-box/cmd_rule_set_match.go +++ b/cmd/sing-box/cmd_rule_set_match.go @@ -5,6 +5,7 @@ import ( "context" "io" "os" + "path/filepath" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/srs" @@ -56,6 +57,14 @@ func ruleSetMatch(sourcePath string, domain string) error { if err != nil { return E.Cause(err, "read rule-set") } + if flagRuleSetMatchFormat == "" { + switch filepath.Ext(sourcePath) { + case ".json": + flagRuleSetMatchFormat = C.RuleSetFormatSource + case ".srs": + flagRuleSetMatchFormat = C.RuleSetFormatBinary + } + } var ruleSet option.PlainRuleSetCompat switch flagRuleSetMatchFormat { case C.RuleSetFormatSource: diff --git a/docs/configuration/rule-set/index.md b/docs/configuration/rule-set/index.md index c905e110..ea278608 100644 --- a/docs/configuration/rule-set/index.md +++ b/docs/configuration/rule-set/index.md @@ -84,6 +84,8 @@ List of [Headless Rule](./headless-rule/). Format of rule-set file, `source` or `binary`. +Optional when `path` or `url` uses `json` or `srs` as extension. + ### Local Fields #### path diff --git a/docs/configuration/rule-set/index.zh.md b/docs/configuration/rule-set/index.zh.md index c3b86b6d..17fdfa5a 100644 --- a/docs/configuration/rule-set/index.zh.md +++ b/docs/configuration/rule-set/index.zh.md @@ -84,6 +84,8 @@ icon: material/new-box 规则集格式, `source` 或 `binary`。 +当 `path` 或 `url` 使用 `json` 或 `srs` 作为扩展名时可选。 + ### 本地字段 #### path diff --git a/option/rule_set.go b/option/rule_set.go index bf644764..610d7ba2 100644 --- a/option/rule_set.go +++ b/option/rule_set.go @@ -1,6 +1,8 @@ package option import ( + "net/url" + "path/filepath" "reflect" C "github.com/sagernet/sing-box/constant" @@ -27,6 +29,18 @@ type _RuleSet struct { type RuleSet _RuleSet func (r RuleSet) MarshalJSON() ([]byte, error) { + if r.Type != C.RuleSetTypeInline { + var defaultFormat string + switch r.Type { + case C.RuleSetTypeLocal: + defaultFormat = ruleSetDefaultFormat(r.LocalOptions.Path) + case C.RuleSetTypeRemote: + defaultFormat = ruleSetDefaultFormat(r.RemoteOptions.URL) + } + if r.Format == defaultFormat { + r.Format = "" + } + } var v any switch r.Type { case "", C.RuleSetTypeInline: @@ -62,7 +76,19 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error { default: return E.New("unknown rule-set type: " + r.Type) } + err = badjson.UnmarshallExcluded(bytes, (*_RuleSet)(r), v) + if err != nil { + return err + } if r.Type != C.RuleSetTypeInline { + if r.Format == "" { + switch r.Type { + case C.RuleSetTypeLocal: + r.Format = ruleSetDefaultFormat(r.LocalOptions.Path) + case C.RuleSetTypeRemote: + r.Format = ruleSetDefaultFormat(r.RemoteOptions.URL) + } + } switch r.Format { case "": return E.New("missing format") @@ -73,13 +99,23 @@ func (r *RuleSet) UnmarshalJSON(bytes []byte) error { } else { r.Format = "" } - err = badjson.UnmarshallExcluded(bytes, (*_RuleSet)(r), v) - if err != nil { - return err - } return nil } +func ruleSetDefaultFormat(path string) string { + if pathURL, err := url.Parse(path); err == nil { + path = pathURL.Path + } + switch filepath.Ext(path) { + case ".json": + return C.RuleSetFormatSource + case ".srs": + return C.RuleSetFormatBinary + default: + return "" + } +} + type LocalRuleSet struct { Path string `json:"path,omitempty"` }