diff --git a/app/discovery/discovery.go b/app/discovery/discovery.go index 94b45434..a8a027a3 100644 --- a/app/discovery/discovery.go +++ b/app/discovery/discovery.go @@ -165,6 +165,15 @@ func (s *Service) Run(ctx context.Context) error { // For MTStatic always a single match because fail-over doesn't supported for assets func (s *Service) Match(srv, src string) (res Matches) { + replaceHost := func(dest, srv string) string { + // $host or ${host} in dest replaced by srv + dest = strings.ReplaceAll(dest, "$host", srv) + if strings.Contains(dest, "${host}") { + dest = strings.ReplaceAll(dest, "${host}", srv) + } + return dest + } + s.lock.RLock() defer s.lock.RUnlock() @@ -179,8 +188,9 @@ func (s *Service) Match(srv, src string) (res Matches) { switch m.MatchType { case MTProxy: - dest := m.SrcMatch.ReplaceAllString(src, m.Dst) - if src != dest { // regex matched + dest := replaceHost(m.Dst, srv) // replace $host and ${host} in dest first, before regex match + dest = m.SrcMatch.ReplaceAllString(src, dest) + if src != dest { // regex matched because dest changed after replacement lastSrcMatch = m.SrcMatch.String() res.MatchType = MTProxy res.Routes = append(res.Routes, MatchedRoute{Destination: dest, Alive: m.IsAlive(), Mapper: m}) diff --git a/app/discovery/discovery_test.go b/app/discovery/discovery_test.go index 4bb0de8e..7ff1b18b 100644 --- a/app/discovery/discovery_test.go +++ b/app/discovery/discovery_test.go @@ -164,7 +164,6 @@ func TestService_Match(t *testing.T) { } for i, tt := range tbl { - tt := tt t.Run(strconv.Itoa(i)+"-"+tt.server, func(t *testing.T) { res := svc.Match(tt.server, tt.src) require.Equal(t, len(tt.res.Routes), len(res.Routes), res.Routes) @@ -192,8 +191,8 @@ func TestService_MatchServerRegex(t *testing.T) { Dst: "http://127.0.0.10:8080/", MatchType: MTProxy, dead: false}, // regex servers - {Server: "test-prefix\\.(.*)", SrcMatch: *regexp.MustCompile("^/"), - Dst: "http://127.0.0.1:8080/", MatchType: MTProxy, dead: false}, + {Server: "test-prefix\\.(.*)", SrcMatch: *regexp.MustCompile("^/(.*)"), + Dst: "http://127.0.0.1:8080/$host/blah/$1", MatchType: MTProxy, dead: false}, {Server: "(.*)\\.test-domain\\.(com|org)", SrcMatch: *regexp.MustCompile("^/"), Dst: "http://127.0.0.2:8080/", MatchType: MTProxy, dead: false}, @@ -212,21 +211,43 @@ func TestService_MatchServerRegex(t *testing.T) { assert.Equal(t, context.DeadlineExceeded, err) tbl := []struct { + name string server, src string res Matches }{ - // strict match should take priority - {"test-prefix.exact.com", "/", Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.4:8080/", Alive: true}}}}, - - // regex servers - {"test-prefix.example.com", "/", Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.1:8080/", Alive: true}}}}, - {"another-prefix.example.com", "/", Matches{MTProxy, nil}}, - {"another-prefix.test-domain.org", "/", Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.2:8080/", Alive: true}}}}, - {"another-prefix.test-domain.net", "/", Matches{MTProxy, nil}}, + { + name: "strict match", + server: "test-prefix.exact.com", + src: "/", + res: Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.4:8080/", Alive: true}}}, + }, + { + name: "regex server with host match", + server: "test-prefix.example.com", + src: "/some", + res: Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.1:8080/test-prefix.example.com/blah/some", Alive: true}}}, + }, + { + name: "regex server without a match", + server: "another-prefix.example.com", + src: "/", + res: Matches{MTProxy, nil}, + }, + { + name: "regex server with test-domain.org match", + server: "another-prefix.test-domain.org", + src: "/", + res: Matches{MTProxy, []MatchedRoute{{Destination: "http://127.0.0.2:8080/", Alive: true}}}, + }, + { + name: "regex server with test-domain.net mismatch", + server: "another-prefix.test-domain.net", + src: "/", + res: Matches{MTProxy, nil}, + }, } for i, tt := range tbl { - tt := tt t.Run(strconv.Itoa(i)+"-"+tt.server, func(t *testing.T) { res := svc.Match(tt.server, tt.src) require.Equal(t, len(tt.res.Routes), len(res.Routes), res.Routes) @@ -374,7 +395,6 @@ func TestService_Servers(t *testing.T) { } func TestService_extendRule(t *testing.T) { - tbl := []struct { inp URLMapper out URLMapper @@ -411,11 +431,9 @@ func TestService_extendRule(t *testing.T) { assert.Equal(t, tt.out, res) }) } - } func TestService_redirects(t *testing.T) { - tbl := []struct { inp URLMapper out URLMapper