Skip to content

Commit

Permalink
Handle default and concrete server match conflict #192
Browse files Browse the repository at this point in the history
- Drop default server match if a concrete server match is found
- Add test case to validate behavior
  • Loading branch information
umputun committed May 23, 2024
1 parent 084e167 commit 5774737
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
10 changes: 10 additions & 0 deletions app/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,16 @@ func (s *Service) Match(srv, src string) (res Matches) {
}
}

// if match returns both default and concrete server(s), drop default as we have a better match with concrete
if len(res.Routes) > 1 {
for i := range res.Routes {
if res.Routes[i].Mapper.Server == "*" || res.Routes[i].Mapper.Server == "" {
res.Routes = append(res.Routes[:i], res.Routes[i+1:]...)
break
}
}
}

return res
}

Expand Down
67 changes: 67 additions & 0 deletions app/discovery/discovery_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,73 @@ func TestService_MatchConflictRegex(t *testing.T) {
}
}

// https://github.com/umputun/reproxy/issues/192
func TestService_Match192(t *testing.T) {
p1 := &ProviderMock{
EventsFunc: func(ctx context.Context) <-chan ProviderID {
res := make(chan ProviderID, 1)
res <- PIFile
return res
},
ListFunc: func() ([]URLMapper, error) {
return []URLMapper{
{
Server: "*",
SrcMatch: *regexp.MustCompile("^/(.*)"),
Dst: "@temp https://site1.ru/",
ProviderID: PIFile,
},
{
Server: "example1.ru",
SrcMatch: *regexp.MustCompile("^/(.*)"),
Dst: "@temp https://site2.ru/",
ProviderID: PIFile,
},
{
Server: "example2.ru",
SrcMatch: *regexp.MustCompile("^/(.*)"),
Dst: "@temp https://site2.ru/",
ProviderID: PIFile,
},
}, nil
},
}

svc := NewService([]Provider{p1}, time.Millisecond*100)
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()

err := svc.Run(ctx)
require.Error(t, err)
assert.Equal(t, context.DeadlineExceeded, err)
assert.Equal(t, 3, len(svc.Mappers()))

tbl := []struct {
server, src string
res Matches
}{
{"example2.ru", "/something", Matches{MTProxy, []MatchedRoute{
{Destination: "https://site2.ru/", Alive: true}}}},
{"example1.ru", "/something", Matches{MTProxy, []MatchedRoute{
{Destination: "https://site2.ru/", Alive: true}}}},
{"example123.ru", "/something", Matches{MTProxy, []MatchedRoute{
{Destination: "https://site1.ru/", Alive: true}}}},
}

for i, tt := range tbl {
tt := tt
t.Run(strconv.Itoa(i), func(t *testing.T) {
res := svc.Match(tt.server, tt.src)
require.Equal(t, len(tt.res.Routes), len(res.Routes), res.Routes)
for i := 0; i < len(res.Routes); i++ {
assert.Equal(t, tt.res.Routes[i].Alive, res.Routes[i].Alive)
assert.Equal(t, tt.res.Routes[i].Destination, res.Routes[i].Destination)
}
assert.Equal(t, tt.res.MatchType, res.MatchType)
})
}
}

func TestService_Servers(t *testing.T) {
p1 := &ProviderMock{
EventsFunc: func(ctx context.Context) <-chan ProviderID {
Expand Down

0 comments on commit 5774737

Please sign in to comment.