update for latest micro, drop rutil usage

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2021-09-30 03:00:24 +03:00
parent 776ce8591a
commit 06a0a2f336
4 changed files with 37 additions and 75 deletions

2
go.mod
View File

@ -3,6 +3,6 @@ module github.com/unistack-org/micro-server-http/v3
go 1.16 go 1.16
require ( 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 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
) )

4
go.sum
View File

@ -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/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 h1:KrWLS4FUX7UAWNAilQf70uad6ZPf/0EudeddCXllRVc=
github.com/unistack-org/micro-proto v0.0.9/go.mod h1:Cckwmzd89gvS7ThxzZp9kQR/EOdksFQcsTAtDDyKwrg= 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.6 h1:cobNkaicZR+8nbDWRUmX3/CSLh6ZNSytK2zWth4s4IM=
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/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 h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -14,8 +14,8 @@ import (
"github.com/unistack-org/micro/v3/metadata" "github.com/unistack-org/micro/v3/metadata"
"github.com/unistack-org/micro/v3/register" "github.com/unistack-org/micro/v3/register"
"github.com/unistack-org/micro/v3/server" "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" rflutil "github.com/unistack-org/micro/v3/util/reflect"
rutil "github.com/unistack-org/micro/v3/util/router"
) )
var ( var (
@ -32,7 +32,7 @@ type patHandler struct {
mtype *methodType mtype *methodType
rcvr reflect.Value rcvr reflect.Value
name string name string
pat rutil.Pattern pat *rhttp.Trie
} }
type httpHandler struct { type httpHandler struct {
@ -62,12 +62,10 @@ func (h *httpHandler) Options() server.HandlerOptions {
} }
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for exp, ph := range h.pathHandlers { if ph, _, ok := h.pathHandlers.Search(r.Method, r.URL.Path); ok {
if exp.MatchString(r.URL.String()) { ph.(http.HandlerFunc)(w, r)
ph(w, r)
return return
} }
}
ct := DefaultContentType ct := DefaultContentType
if htype := r.Header.Get("Content-Type"); htype != "" { if htype := r.Header.Get("Content-Type"); htype != "" {
@ -113,30 +111,19 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return 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{}) matches := make(map[string]interface{})
var match bool var match bool
var hldr patHandler var hldr patHandler
var handler *httpHandler var handler *httpHandler
fmt.Printf("try to find handler\n")
for _, hpat := range h.handlers { for _, hpat := range h.handlers {
handlertmp := hpat.(*httpHandler) handlertmp := hpat.(*httpHandler)
for _, hldrtmp := range handlertmp.handlers[r.Method] { for _, hldrtmp := range handlertmp.handlers[r.Method] {
mp, merr := hldrtmp.pat.Match(components, verb) fmt.Printf("ssss method %v path %v %#+v\n", r.Method, path, hldrtmp)
if merr == nil { _, mp, ok := hldrtmp.pat.Search(r.Method, path)
if ok {
match = true match = true
for k, v := range mp { for k, v := range mp {
matches[k] = v matches[k] = v

75
http.go
View File

@ -8,7 +8,6 @@ import (
"net" "net"
"net/http" "net/http"
"reflect" "reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"sync" "sync"
@ -19,10 +18,22 @@ import (
"github.com/unistack-org/micro/v3/logger" "github.com/unistack-org/micro/v3/logger"
"github.com/unistack-org/micro/v3/register" "github.com/unistack-org/micro/v3/register"
"github.com/unistack-org/micro/v3/server" "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" "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 { type httpServer struct {
hd server.Handler hd server.Handler
rsvc *register.Service rsvc *register.Service
@ -30,7 +41,7 @@ type httpServer struct {
exit chan chan error exit chan chan error
subscribers map[*httpSubscriber][]broker.Subscriber subscribers map[*httpSubscriber][]broker.Subscriber
errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int) 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 contentTypeHandlers map[string]http.HandlerFunc
opts server.Options opts server.Options
registerRPC bool registerRPC bool
@ -76,7 +87,7 @@ func (h *httpServer) Init(opts ...server.Option) error {
h.handlers = make(map[string]server.Handler) h.handlers = make(map[string]server.Handler)
} }
if h.pathHandlers == nil { if h.pathHandlers == nil {
h.pathHandlers = make(map[*regexp.Regexp]http.HandlerFunc) h.pathHandlers = rhttp.NewTrie()
} }
if h.contentTypeHandlers == nil { if h.contentTypeHandlers == nil {
h.contentTypeHandlers = make(map[string]http.HandlerFunc) 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 { if phs, ok := h.opts.Context.Value(pathHandlerKey{}).(*pathHandlerVal); ok && phs.h != nil {
for pp, ph := range phs.h { for pp, ph := range phs.h {
exp, err := regexp.Compile(pp) h.pathHandlers.Insert(httpAllMethods, pp, ph)
if err != nil {
h.Unlock()
return err
}
h.pathHandlers[exp] = ph
} }
} }
if phs, ok := h.opts.Context.Value(contentTypeHandlerKey{}).(*contentTypeHandlerVal); ok && phs.h != nil { 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) tp := reflect.TypeOf(handler)
type nilHandler struct{}
/*
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)
}
}
*/
hdlr.handlers = make(map[string][]patHandler) hdlr.handlers = make(map[string][]patHandler)
for hn, md := range options.Metadata { for hn, md := range options.Metadata {
cmp, err := rutil.Parse(md["Path"]) pat := rhttp.NewTrie()
if err != nil && h.opts.Logger.V(logger.ErrorLevel) { pat.Insert([]string{md["Method"]}, md["Path"], &nilHandler{})
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
}
var method reflect.Method var method reflect.Method
mname := hn[strings.Index(hn, ".")+1:] mname := hn[strings.Index(hn, ".")+1:]
@ -251,18 +234,10 @@ func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOptio
continue continue
} }
cmp, err = rutil.Parse("/" + hn) rpat := rhttp.NewTrie()
if err != nil && h.opts.Logger.V(logger.ErrorLevel) { rpat.Insert([]string{http.MethodPost}, "/"+hn, &nilHandler{})
h.opts.Logger.Errorf(h.opts.Context, "parsing path pattern err: %v", err)
continue pth = patHandler{pat: rpat, mtype: mtype, name: name, rcvr: rcvr}
}
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}
hdlr.handlers[http.MethodPost] = append(hdlr.handlers[http.MethodPost], pth) hdlr.handlers[http.MethodPost] = append(hdlr.handlers[http.MethodPost], pth)
} }
@ -533,7 +508,7 @@ func (h *httpServer) Start() error {
if srvFunc != nil { if srvFunc != nil {
go func() { 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) h.opts.Logger.Error(h.opts.Context, cerr)
} }
}() }()
@ -634,6 +609,6 @@ func NewServer(opts ...server.Option) server.Server {
exit: make(chan chan error), exit: make(chan chan error),
subscribers: make(map[*httpSubscriber][]broker.Subscriber), subscribers: make(map[*httpSubscriber][]broker.Subscriber),
errorHandler: DefaultErrorHandler, errorHandler: DefaultErrorHandler,
pathHandlers: make(map[*regexp.Regexp]http.HandlerFunc), pathHandlers: rhttp.NewTrie(),
} }
} }