From 06a0a2f336650b91f8589e1f4e403057a422b2d1 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 30 Sep 2021 03:00:24 +0300 Subject: [PATCH] update for latest micro, drop rutil usage Signed-off-by: Vasiliy Tolstov --- go.mod | 2 +- go.sum | 4 +-- handler.go | 31 +++++++--------------- http.go | 75 ++++++++++++++++++------------------------------------ 4 files changed, 37 insertions(+), 75 deletions(-) diff --git a/go.mod b/go.mod index 5931337..5fb4e09 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/unistack-org/micro-server-http/v3 go 1.16 require ( - github.com/unistack-org/micro/v3 v3.7.5 + github.com/unistack-org/micro/v3 v3.7.6 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b ) diff --git a/go.sum b/go.sum index c33c2b0..dbd5563 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/silas/dag v0.0.0-20210626123444-3804bac2d6d4/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= github.com/unistack-org/micro-proto v0.0.9 h1:KrWLS4FUX7UAWNAilQf70uad6ZPf/0EudeddCXllRVc= github.com/unistack-org/micro-proto v0.0.9/go.mod h1:Cckwmzd89gvS7ThxzZp9kQR/EOdksFQcsTAtDDyKwrg= -github.com/unistack-org/micro/v3 v3.7.5 h1:ucNsxi6mApYRpYHbiNKqTLY3V8oGQDfnHn+AbtnFBdo= -github.com/unistack-org/micro/v3 v3.7.5/go.mod h1:Ke/8WJlNZi4ZYwL9HcsANAbQ66/HocTBEZM+od99/mM= +github.com/unistack-org/micro/v3 v3.7.6 h1:cobNkaicZR+8nbDWRUmX3/CSLh6ZNSytK2zWth4s4IM= +github.com/unistack-org/micro/v3 v3.7.6/go.mod h1:Ke/8WJlNZi4ZYwL9HcsANAbQ66/HocTBEZM+od99/mM= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/handler.go b/handler.go index 788a282..63e3a56 100644 --- a/handler.go +++ b/handler.go @@ -14,8 +14,8 @@ import ( "github.com/unistack-org/micro/v3/metadata" "github.com/unistack-org/micro/v3/register" "github.com/unistack-org/micro/v3/server" + rhttp "github.com/unistack-org/micro/v3/util/http" rflutil "github.com/unistack-org/micro/v3/util/reflect" - rutil "github.com/unistack-org/micro/v3/util/router" ) var ( @@ -32,7 +32,7 @@ type patHandler struct { mtype *methodType rcvr reflect.Value name string - pat rutil.Pattern + pat *rhttp.Trie } type httpHandler struct { @@ -62,11 +62,9 @@ func (h *httpHandler) Options() server.HandlerOptions { } func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - for exp, ph := range h.pathHandlers { - if exp.MatchString(r.URL.String()) { - ph(w, r) - return - } + if ph, _, ok := h.pathHandlers.Search(r.Method, r.URL.Path); ok { + ph.(http.HandlerFunc)(w, r) + return } ct := DefaultContentType @@ -113,30 +111,19 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - components := strings.Split(path[1:], "/") - l := len(components) - var verb string - idx := strings.LastIndex(components[l-1], ":") - if idx == 0 { - h.errorHandler(ctx, nil, w, r, fmt.Errorf("not found"), http.StatusNotFound) - return - } - if idx > 0 { - c := components[l-1] - components[l-1], verb = c[:idx], c[idx+1:] - } - matches := make(map[string]interface{}) var match bool var hldr patHandler var handler *httpHandler + fmt.Printf("try to find handler\n") for _, hpat := range h.handlers { handlertmp := hpat.(*httpHandler) for _, hldrtmp := range handlertmp.handlers[r.Method] { - mp, merr := hldrtmp.pat.Match(components, verb) - if merr == nil { + fmt.Printf("ssss method %v path %v %#+v\n", r.Method, path, hldrtmp) + _, mp, ok := hldrtmp.pat.Search(r.Method, path) + if ok { match = true for k, v := range mp { matches[k] = v diff --git a/http.go b/http.go index e36b80c..ece6b1c 100644 --- a/http.go +++ b/http.go @@ -8,7 +8,6 @@ import ( "net" "net/http" "reflect" - "regexp" "sort" "strings" "sync" @@ -19,10 +18,22 @@ import ( "github.com/unistack-org/micro/v3/logger" "github.com/unistack-org/micro/v3/register" "github.com/unistack-org/micro/v3/server" - rutil "github.com/unistack-org/micro/v3/util/router" + rhttp "github.com/unistack-org/micro/v3/util/http" "golang.org/x/net/netutil" ) +var httpAllMethods = []string{ + http.MethodConnect, + http.MethodDelete, + http.MethodGet, + http.MethodHead, + http.MethodOptions, + http.MethodPatch, + http.MethodPost, + http.MethodPut, + http.MethodTrace, +} + type httpServer struct { hd server.Handler rsvc *register.Service @@ -30,7 +41,7 @@ type httpServer struct { exit chan chan error subscribers map[*httpSubscriber][]broker.Subscriber errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int) - pathHandlers map[*regexp.Regexp]http.HandlerFunc + pathHandlers *rhttp.Trie contentTypeHandlers map[string]http.HandlerFunc opts server.Options registerRPC bool @@ -76,7 +87,7 @@ func (h *httpServer) Init(opts ...server.Option) error { h.handlers = make(map[string]server.Handler) } if h.pathHandlers == nil { - h.pathHandlers = make(map[*regexp.Regexp]http.HandlerFunc) + h.pathHandlers = rhttp.NewTrie() } if h.contentTypeHandlers == nil { h.contentTypeHandlers = make(map[string]http.HandlerFunc) @@ -88,12 +99,7 @@ func (h *httpServer) Init(opts ...server.Option) error { if phs, ok := h.opts.Context.Value(pathHandlerKey{}).(*pathHandlerVal); ok && phs.h != nil { for pp, ph := range phs.h { - exp, err := regexp.Compile(pp) - if err != nil { - h.Unlock() - return err - } - h.pathHandlers[exp] = ph + h.pathHandlers.Insert(httpAllMethods, pp, ph) } } if phs, ok := h.opts.Context.Value(contentTypeHandlerKey{}).(*contentTypeHandlerVal); ok && phs.h != nil { @@ -186,35 +192,12 @@ func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOptio } tp := reflect.TypeOf(handler) - - /* - for m := 0; m < tp.NumMethod(); m++ { - if e := register.ExtractEndpoint(tp.Method(m)); e != nil { - e.Name = name + "." + e.Name - - for k, v := range options.Metadata[e.Name] { - e.Metadata[k] = v - } - - eps = append(eps, e) - } - } - - */ + type nilHandler struct{} hdlr.handlers = make(map[string][]patHandler) for hn, md := range options.Metadata { - cmp, err := rutil.Parse(md["Path"]) - if err != nil && h.opts.Logger.V(logger.ErrorLevel) { - h.opts.Logger.Errorf(h.opts.Context, "parsing path pattern err: %v", err) - continue - } - tpl := cmp.Compile() - pat, err := rutil.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, tpl.Verb) - if err != nil && h.opts.Logger.V(logger.ErrorLevel) { - h.opts.Logger.Errorf(h.opts.Context, "creating new pattern err: %v", err) - continue - } + pat := rhttp.NewTrie() + pat.Insert([]string{md["Method"]}, md["Path"], &nilHandler{}) var method reflect.Method mname := hn[strings.Index(hn, ".")+1:] @@ -251,18 +234,10 @@ func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOptio continue } - cmp, err = rutil.Parse("/" + hn) - if err != nil && h.opts.Logger.V(logger.ErrorLevel) { - h.opts.Logger.Errorf(h.opts.Context, "parsing path pattern err: %v", err) - continue - } - tpl = cmp.Compile() - pat, err = rutil.NewPattern(tpl.Version, tpl.OpCodes, tpl.Pool, tpl.Verb) - if err != nil && h.opts.Logger.V(logger.ErrorLevel) { - h.opts.Logger.Errorf(h.opts.Context, "creating new pattern err: %v", err) - continue - } - pth = patHandler{pat: pat, mtype: mtype, name: name, rcvr: rcvr} + rpat := rhttp.NewTrie() + rpat.Insert([]string{http.MethodPost}, "/"+hn, &nilHandler{}) + + pth = patHandler{pat: rpat, mtype: mtype, name: name, rcvr: rcvr} hdlr.handlers[http.MethodPost] = append(hdlr.handlers[http.MethodPost], pth) } @@ -533,7 +508,7 @@ func (h *httpServer) Start() error { if srvFunc != nil { go func() { - if cerr := srvFunc(ts); cerr != nil { + if cerr := srvFunc(ts); cerr != nil && !strings.Contains(cerr.Error(), "use of closed network connection") { h.opts.Logger.Error(h.opts.Context, cerr) } }() @@ -634,6 +609,6 @@ func NewServer(opts ...server.Option) server.Server { exit: make(chan chan error), subscribers: make(map[*httpSubscriber][]broker.Subscriber), errorHandler: DefaultErrorHandler, - pathHandlers: make(map[*regexp.Regexp]http.HandlerFunc), + pathHandlers: rhttp.NewTrie(), } }