api/router: avoid unneeded loops and fix path match (#1594)

* api/router: avoid unneeded loops and fix path match

* if match found in google api path syntax, not try pcre loop
* if path is not ending via $ sign, append it to pcre to avoid matching other strings like
  /api/account/register can be matched to /api/account
* api: add tests and validations

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-04-29 15:23:10 +03:00
parent 5821c18193
commit 01c824bbfa

View File

@ -110,10 +110,14 @@ func (r *staticRouter) Register(ep *api.Endpoint) error {
for _, p := range ep.Path { for _, p := range ep.Path {
var pcreok bool var pcreok bool
pcrereg, err := regexp.CompilePOSIX(p)
if err == nil { // pcre only when we have start and end markers
pcreregs = append(pcreregs, pcrereg) if p[0] == '^' && p[len(p)-1] == '$' {
pcreok = true pcrereg, err := regexp.CompilePOSIX(p)
if err == nil {
pcreregs = append(pcreregs, pcrereg)
pcreok = true
}
} }
rule, err := util.Parse(p) rule, err := util.Parse(p)
@ -122,6 +126,7 @@ func (r *staticRouter) Register(ep *api.Endpoint) error {
} else if err != nil && pcreok { } else if err != nil && pcreok {
continue continue
} }
tpl := rule.Compile() tpl := rule.Compile()
pathreg, err := util.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "") pathreg, err := util.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, "")
if err != nil { if err != nil {
@ -280,6 +285,9 @@ func (r *staticRouter) endpoint(req *http.Request) (*endpoint, error) {
} }
continue continue
} }
if logger.V(logger.DebugLevel, logger.DefaultLogger) {
logger.Debugf("api gpath match %s = %v", path, pathreg)
}
pMatch = true pMatch = true
ctx := req.Context() ctx := req.Context()
md, ok := metadata.FromContext(ctx) md, ok := metadata.FromContext(ctx)
@ -294,16 +302,18 @@ func (r *staticRouter) endpoint(req *http.Request) (*endpoint, error) {
break break
} }
// 4. try path via pcre path matching if !pMatch {
for _, pathreg := range ep.pcreregs { // 4. try path via pcre path matching
if !pathreg.MatchString(req.URL.Path) { for _, pathreg := range ep.pcreregs {
if logger.V(logger.DebugLevel, logger.DefaultLogger) { if !pathreg.MatchString(req.URL.Path) {
logger.Debugf("api pcre path not match %s != %v", req.URL.Path, pathreg) if logger.V(logger.DebugLevel, logger.DefaultLogger) {
logger.Debugf("api pcre path not match %s != %v", req.URL.Path, pathreg)
}
continue
} }
continue pMatch = true
break
} }
pMatch = true
break
} }
if !pMatch { if !pMatch {