mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Invalidate remote rule-set cache when URL changes
This commit is contained in:
+25
-1
@@ -61,11 +61,12 @@ type SavedBinary struct {
|
||||
Content []byte
|
||||
LastUpdated time.Time
|
||||
LastEtag string
|
||||
URLHash []byte
|
||||
}
|
||||
|
||||
func (s *SavedBinary) MarshalBinary() ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
err := binary.Write(&buffer, binary.BigEndian, uint8(1))
|
||||
err := binary.Write(&buffer, binary.BigEndian, uint8(2))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -89,6 +90,14 @@ func (s *SavedBinary) MarshalBinary() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = varbin.WriteUvarint(&buffer, uint64(len(s.URLHash)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = buffer.Write(s.URLHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
@@ -130,6 +139,21 @@ func (s *SavedBinary) UnmarshalBinary(data []byte) error {
|
||||
return err
|
||||
}
|
||||
s.LastEtag = string(etagBytes)
|
||||
if version < 2 {
|
||||
return nil
|
||||
}
|
||||
urlHashLength, err := binary.ReadUvarint(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if urlHashLength > uint64(reader.Len()) {
|
||||
return E.New("invalid url hash length: ", urlHashLength)
|
||||
}
|
||||
s.URLHash = make([]byte, urlHashLength)
|
||||
_, err = io.ReadFull(reader, s.URLHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package rule
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
@@ -38,6 +39,7 @@ type RemoteRuleSet struct {
|
||||
outbound adapter.OutboundManager
|
||||
tag string
|
||||
url string
|
||||
urlHash [32]byte
|
||||
initialPath string
|
||||
options option.RuleSet
|
||||
updateInterval time.Duration
|
||||
@@ -66,13 +68,15 @@ func NewRemoteRuleSet(ctx context.Context, logger logger.ContextLogger, tag stri
|
||||
initialPath = filemanager.BasePath(ctx, strings.ReplaceAll(options.RemoteOptions.InitialPath, C.RuleSetTagPlaceholder, tag))
|
||||
initialPath, _ = filepath.Abs(initialPath)
|
||||
}
|
||||
url := strings.ReplaceAll(options.RemoteOptions.URL, C.RuleSetTagPlaceholder, tag)
|
||||
return &RemoteRuleSet{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
outbound: service.FromContext[adapter.OutboundManager](ctx),
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
url: strings.ReplaceAll(options.RemoteOptions.URL, C.RuleSetTagPlaceholder, tag),
|
||||
url: url,
|
||||
urlHash: sha256.Sum256([]byte(url)),
|
||||
initialPath: initialPath,
|
||||
options: options,
|
||||
updateInterval: updateInterval,
|
||||
@@ -97,13 +101,18 @@ func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.
|
||||
startContext.Register(transport)
|
||||
s.httpClient = &http.Client{Transport: transport}
|
||||
if s.cacheFile != nil {
|
||||
if savedSet := s.cacheFile.LoadRuleSet(s.tag); savedSet != nil {
|
||||
err = s.loadBytes(savedSet.Content)
|
||||
if err != nil {
|
||||
s.logger.Warn(E.Cause(err, "restore cached rule-set, will refetch"))
|
||||
savedSet := s.cacheFile.LoadRuleSet(s.tag)
|
||||
if savedSet != nil {
|
||||
if len(savedSet.URLHash) > 0 && !bytes.Equal(savedSet.URLHash, s.urlHash[:]) {
|
||||
s.logger.Info("cached rule-set was downloaded from another URL, will refetch")
|
||||
} else {
|
||||
s.lastUpdated = savedSet.LastUpdated
|
||||
s.lastEtag = savedSet.LastEtag
|
||||
err = s.loadBytes(savedSet.Content)
|
||||
if err != nil {
|
||||
s.logger.Warn(E.Cause(err, "restore cached rule-set, will refetch"))
|
||||
} else {
|
||||
s.lastUpdated = savedSet.LastUpdated
|
||||
s.lastEtag = savedSet.LastEtag
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,6 +258,7 @@ func (s *RemoteRuleSet) fetch(ctx context.Context, isStart bool) error {
|
||||
savedRuleSet := s.cacheFile.LoadRuleSet(s.tag)
|
||||
if savedRuleSet != nil {
|
||||
savedRuleSet.LastUpdated = s.lastUpdated
|
||||
savedRuleSet.URLHash = s.urlHash[:]
|
||||
err = s.cacheFile.SaveRuleSet(s.tag, savedRuleSet)
|
||||
if err != nil {
|
||||
s.logger.Error("save rule-set updated time: ", err)
|
||||
@@ -279,6 +289,7 @@ func (s *RemoteRuleSet) fetch(ctx context.Context, isStart bool) error {
|
||||
LastUpdated: s.lastUpdated,
|
||||
Content: content,
|
||||
LastEtag: s.lastEtag,
|
||||
URLHash: s.urlHash[:],
|
||||
})
|
||||
if err != nil {
|
||||
s.logger.Error("save rule-set cache: ", err)
|
||||
|
||||
Reference in New Issue
Block a user