rewrite: storage
This commit is contained in:
parent
ff91bb81a6
commit
f10a45361c
|
@ -16,14 +16,14 @@ type Storage interface {
|
||||||
// Match finds a matching rule for the specified hostname.
|
// Match finds a matching rule for the specified hostname.
|
||||||
Match(hostname string) (res *urlfilter.DNSResult, matched bool)
|
Match(hostname string) (res *urlfilter.DNSResult, matched bool)
|
||||||
|
|
||||||
// AddRule creates rule from text and adds it to the storage.
|
// Add adds item to the storage.
|
||||||
AddRule(line string) (err error)
|
Add(item *Item) (err error)
|
||||||
|
|
||||||
// ReadRules returns all rules from the storage.
|
// Remove deletes item from the storage.
|
||||||
ReadRules() (lines []string)
|
Remove(item *Item) (err error)
|
||||||
|
|
||||||
// RemoveRule deletes rule from the storage.
|
// List returns all items from the storage.
|
||||||
RemoveRule(line string) (err error)
|
List() (items []*Item)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultStorage is the default storage for rewrite rules.
|
// DefaultStorage is the default storage for rewrite rules.
|
||||||
|
@ -43,23 +43,38 @@ type DefaultStorage struct {
|
||||||
// remove this crutch.
|
// remove this crutch.
|
||||||
urlFilterID int
|
urlFilterID int
|
||||||
|
|
||||||
// rulesText is an array of rule lines.
|
// rewrites is an array of rewrite items.
|
||||||
rulesText []string
|
// TODO(d.kolyshev): Use filtering.Config.Rewrites?
|
||||||
|
rewrites []*Item
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultStorageConfig contains configuration for a rewrite storage.
|
// Item is a single DNS rewrite record.
|
||||||
type DefaultStorageConfig struct {
|
type Item struct {
|
||||||
// rulesText is an array of rule lines.
|
// Domain is the domain pattern for which this rewrite should work.
|
||||||
rulesText []string
|
Domain string `yaml:"domain"`
|
||||||
|
|
||||||
|
// Answer is the IP address, canonical name, or one of the special
|
||||||
|
// values: "A" or "AAAA".
|
||||||
|
Answer string `yaml:"answer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal returns true if the rw is equal to the other.
|
||||||
|
func (rw *Item) equal(other *Item) (ok bool) {
|
||||||
|
return rw.Domain == other.Domain && rw.Answer == other.Answer
|
||||||
|
}
|
||||||
|
|
||||||
|
// toRule converts this item to a filter rule.
|
||||||
|
func (rw *Item) toRule() (res string) {
|
||||||
|
return fmt.Sprintf("|%s^$dnsrewrite=%s", rw.Domain, rw.Answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaultStorage returns new rewrites storage. listID is used as an
|
// NewDefaultStorage returns new rewrites storage. listID is used as an
|
||||||
// identifier of the underlying rules list. c must not be nil.
|
// identifier of the underlying rules list. rewrites must not be nil.
|
||||||
func NewDefaultStorage(listID int, c *DefaultStorageConfig) (s *DefaultStorage, err error) {
|
func NewDefaultStorage(listID int, rewrites []*Item) (s *DefaultStorage, err error) {
|
||||||
s = &DefaultStorage{
|
s = &DefaultStorage{
|
||||||
mu: &sync.RWMutex{},
|
mu: &sync.RWMutex{},
|
||||||
urlFilterID: listID,
|
urlFilterID: listID,
|
||||||
rulesText: c.rulesText,
|
rewrites: rewrites,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
|
@ -73,13 +88,6 @@ func NewDefaultStorage(listID int, c *DefaultStorageConfig) (s *DefaultStorage,
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config returns storage configuration.
|
|
||||||
func (s *DefaultStorage) Config() (c *DefaultStorageConfig) {
|
|
||||||
return &DefaultStorageConfig{
|
|
||||||
rulesText: s.rulesText,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// type check
|
// type check
|
||||||
var _ Storage = (*DefaultStorage)(nil)
|
var _ Storage = (*DefaultStorage)(nil)
|
||||||
|
|
||||||
|
@ -88,46 +96,55 @@ func (s *DefaultStorage) Match(hostname string) (res *urlfilter.DNSResult, match
|
||||||
return s.engine.Match(hostname)
|
return s.engine.Match(hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRule implements the Storage interface for *DefaultStorage.
|
// Add implements the Storage interface for *DefaultStorage.
|
||||||
func (s *DefaultStorage) AddRule(line string) (err error) {
|
func (s *DefaultStorage) Add(item *Item) (err error) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
s.rulesText = append(s.rulesText, line)
|
s.rewrites = append(s.rewrites, item)
|
||||||
|
|
||||||
return s.resetRules()
|
return s.resetRules()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadRules implements the Storage interface for *DefaultStorage.
|
// Remove implements the Storage interface for *DefaultStorage.
|
||||||
func (s *DefaultStorage) ReadRules() (lines []string) {
|
func (s *DefaultStorage) Remove(item *Item) (err error) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
return s.rulesText
|
arr := []*Item{}
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveRule implements the Storage interface for *DefaultStorage.
|
for _, ent := range s.rewrites {
|
||||||
func (s *DefaultStorage) RemoveRule(line string) (err error) {
|
if ent.equal(item) {
|
||||||
s.mu.Lock()
|
log.Debug("rewrite: removed element: %s -> %s", ent.Domain, ent.Answer)
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
var filtered []string
|
continue
|
||||||
for i, r := range s.rulesText {
|
|
||||||
if r != line {
|
|
||||||
filtered = append(filtered, s.rulesText[i])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.rulesText = filtered
|
arr = append(arr, ent)
|
||||||
|
}
|
||||||
|
s.rewrites = arr
|
||||||
|
|
||||||
return s.resetRules()
|
return s.resetRules()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List implements the Storage interface for *DefaultStorage.
|
||||||
|
func (s *DefaultStorage) List() (items []*Item) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
return s.rewrites
|
||||||
|
}
|
||||||
|
|
||||||
// resetRules resets the filtering rules.
|
// resetRules resets the filtering rules.
|
||||||
func (s *DefaultStorage) resetRules() (err error) {
|
func (s *DefaultStorage) resetRules() (err error) {
|
||||||
|
var rulesText []string
|
||||||
|
for _, rewrite := range s.rewrites {
|
||||||
|
rulesText = append(rulesText, rewrite.toRule())
|
||||||
|
}
|
||||||
|
|
||||||
strList := &filterlist.StringRuleList{
|
strList := &filterlist.StringRuleList{
|
||||||
ID: s.urlFilterID,
|
ID: s.urlFilterID,
|
||||||
RulesText: strings.Join(s.rulesText, "\n"),
|
RulesText: strings.Join(rulesText, "\n"),
|
||||||
IgnoreCosmetic: true,
|
IgnoreCosmetic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewDefaultStorage(t *testing.T) {
|
func TestNewDefaultStorage(t *testing.T) {
|
||||||
c := &DefaultStorageConfig{
|
items := []*Item{{
|
||||||
rulesText: []string{
|
Domain: "example.com",
|
||||||
"|a-record^$dnsrewrite=127.0.0.1",
|
Answer: "answer.com",
|
||||||
},
|
}}
|
||||||
}
|
|
||||||
|
|
||||||
s, err := NewDefaultStorage(-1, c)
|
s, err := NewDefaultStorage(-1, items)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 1, len(s.ReadRules()))
|
require.Equal(t, 1, len(s.List()))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue