From 930b32931007ee58c0be19169de0052446a78357 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sun, 19 Apr 2020 00:31:34 +0300 Subject: [PATCH] api/router: support pcre and google.api pattern matching (#1549) * api/router: support pcre and google.api pattern matching Signed-off-by: Vasiliy Tolstov --- registry.go | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/registry.go b/registry.go index d5cd256..b5ab4d8 100644 --- a/registry.go +++ b/registry.go @@ -23,6 +23,7 @@ import ( type endpoint struct { hostregs []*regexp.Regexp pathregs []util.Pattern + pcreregs []*regexp.Regexp } // router is the default router @@ -185,13 +186,23 @@ func (r *registryRouter) store(services []*registry.Service) { } for _, p := range ep.Endpoint.Path { + var pcreok bool + pcrereg, err := regexp.CompilePOSIX(p) + if err == nil { + cep.pcreregs = append(cep.pcreregs, pcrereg) + pcreok = true + } + rule, err := util.Parse(p) - if err != nil { + if err != nil && !pcreok { if logger.V(logger.TraceLevel, logger.DefaultLogger) { logger.Tracef("endpoint have invalid path pattern: %v", err) } continue + } else if err != nil && pcreok { + continue } + tpl := rule.Compile() pathreg, err := util.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "") if err != nil { @@ -303,11 +314,10 @@ func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) { ep := e.Endpoint var mMatch, hMatch, pMatch bool // 1. try method - methodLoop: for _, m := range ep.Method { if m == req.Method { mMatch = true - break methodLoop + break } } if !mMatch { @@ -321,15 +331,14 @@ func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) { if len(ep.Host) == 0 { hMatch = true } else { - hostLoop: for idx, h := range ep.Host { if h == "" || h == "*" { hMatch = true - break hostLoop + break } else { if cep.hostregs[idx].MatchString(req.URL.Host) { hMatch = true - break hostLoop + break } } } @@ -341,14 +350,12 @@ func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) { logger.Debugf("api host match %s", req.URL.Host) } - // 3. try path - // 3. try path - pathLoop: + // 3. try path via google.api path matching for _, pathreg := range cep.pathregs { matches, err := pathreg.Match(path, "") if err != nil { if logger.V(logger.DebugLevel, logger.DefaultLogger) { - logger.Debugf("api path not match %s != %v", path, pathreg) + logger.Debugf("api gpath not match %s != %v", path, pathreg) } continue } @@ -363,8 +370,21 @@ func (r *registryRouter) Endpoint(req *http.Request) (*api.Service, error) { } md["x-api-body"] = ep.Body *req = *req.Clone(metadata.NewContext(ctx, md)) - break pathLoop + break } + + // 4. try path via pcre path matching + for _, pathreg := range cep.pcreregs { + if !pathreg.MatchString(req.URL.Path) { + if logger.V(logger.DebugLevel, logger.DefaultLogger) { + logger.Debugf("api pcre path not match %s != %v", path, pathreg) + } + continue + } + pMatch = true + break + } + if !pMatch { continue }