From 8733d84ef685cfd4f0f89945171af196e4a7d4da Mon Sep 17 00:00:00 2001 From: Umputun Date: Thu, 8 Apr 2021 23:27:57 -0500 Subject: [PATCH] support extension of rules --- app/discovery/discovery.go | 25 ++++++++++++++++ app/discovery/discovery_test.go | 51 +++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/app/discovery/discovery.go b/app/discovery/discovery.go index 3c3709d..67faf1d 100644 --- a/app/discovery/discovery.go +++ b/app/discovery/discovery.go @@ -7,6 +7,7 @@ package discovery import ( "context" "regexp" + "strings" "sync" log "github.com/go-pkgz/lgr" @@ -124,6 +125,7 @@ func (s *Service) mergeLists() (res []UrlMapper) { continue } for i := range lst { + lst[i] = s.extendRule(lst[i]) lst[i].ProviderID = p.ID() } res = append(res, lst...) @@ -131,6 +133,29 @@ func (s *Service) mergeLists() (res []UrlMapper) { return res } +// extendRule from /something/blah->http://example.com/api to ^/something/blah/(.*)->http://example.com/api/$1 +func (s *Service) extendRule(m UrlMapper) UrlMapper { + + src := m.SrcMatch.String() + if strings.Contains(m.Dst, "$1") || strings.Contains(src, "(") || !strings.HasSuffix(src, "/") { + return m + } + res := UrlMapper{ + Server: m.Server, + Dst: strings.TrimSuffix(m.Dst, "/") + "/$1", + ProviderID: m.ProviderID, + PingURL: m.PingURL, + } + + rx, err := regexp.Compile("^" + strings.TrimSuffix(src, "/") + "/(.*)") + if err != nil { + log.Printf("[WARN] can't extend %s, %v", m.SrcMatch.String(), err) + return m + } + res.SrcMatch = *rx + return res +} + func (s *Service) mergeEvents(ctx context.Context, chs ...<-chan struct{}) <-chan struct{} { var wg sync.WaitGroup out := make(chan struct{}) diff --git a/app/discovery/discovery_test.go b/app/discovery/discovery_test.go index 859af82..719a4cd 100644 --- a/app/discovery/discovery_test.go +++ b/app/discovery/discovery_test.go @@ -49,11 +49,12 @@ func TestService_Do(t *testing.T) { err := svc.Run(ctx) require.Error(t, err) assert.Equal(t, context.DeadlineExceeded, err) - assert.Equal(t, 3, len(svc.mappers)) - assert.Equal(t, PIFile, svc.mappers[0].ProviderID) - assert.Equal(t, "*", svc.mappers[0].Server) - assert.Equal(t, "^/api/svc1/(.*)", svc.mappers[0].SrcMatch.String()) - assert.Equal(t, "http://127.0.0.1:8080/blah1/$1", svc.mappers[0].Dst) + mappers := svc.Mappers() + assert.Equal(t, 3, len(mappers)) + assert.Equal(t, PIFile, mappers[0].ProviderID) + assert.Equal(t, "*", mappers[0].Server) + assert.Equal(t, "^/api/svc1/(.*)", mappers[0].SrcMatch.String()) + assert.Equal(t, "http://127.0.0.1:8080/blah1/$1", mappers[0].Dst) assert.Equal(t, 1, len(p1.EventsCalls())) assert.Equal(t, 1, len(p2.EventsCalls())) @@ -172,3 +173,43 @@ func TestService_Servers(t *testing.T) { assert.Equal(t, []string{"m.example.com", "xx.reproxy.io"}, servers) } + +func TestService_extendRule(t *testing.T) { + + tbl := []struct { + inp UrlMapper + out UrlMapper + }{ + { + UrlMapper{SrcMatch: *regexp.MustCompile("/")}, + UrlMapper{SrcMatch: *regexp.MustCompile("^/(.*)"), Dst: "/$1"}, + }, + { + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("/api/blah/"), Dst: "http://localhost:8080/"}, + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("^/api/blah/(.*)"), Dst: "http://localhost:8080/$1"}, + }, + { + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("/api/blah/(.*)/xxx/(.*_)"), Dst: "http://localhost:8080/$1/$2"}, + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("/api/blah/(.*)/xxx/(.*_)"), Dst: "http://localhost:8080/$1/$2"}, + }, + { + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("/api/blah"), Dst: "http://localhost:8080/xxx"}, + UrlMapper{Server: "m.example.com", PingURL: "http://example.com/ping", ProviderID: "docker", + SrcMatch: *regexp.MustCompile("/api/blah"), Dst: "http://localhost:8080/xxx"}, + }, + } + + svc := &Service{} + for i, tt := range tbl { + t.Run(strconv.Itoa(i), func(t *testing.T) { + res := svc.extendRule(tt.inp) + assert.Equal(t, tt.out, res) + }) + } + +}