From 43357bc790c5326453ed739e6630e364dcb648eb Mon Sep 17 00:00:00 2001 From: Adphi Date: Wed, 13 Oct 2021 17:05:59 +0200 Subject: [PATCH] add http middleware, add option to use custom mux, improved logger kvs --- example/example.go | 20 ++++++++++++++++++-- go.mod | 2 ++ go.sum | 2 ++ logger/logger.go | 8 +++++--- service/gateway.go | 4 ++-- service/mux.go | 15 +++++++++++++++ service/options.go | 24 +++++++++++++++++++++--- service/service.go | 8 +++++--- service/web.go | 4 ++-- 9 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 service/mux.go diff --git a/example/example.go b/example/example.go index 537b269..1b05f4b 100644 --- a/example/example.go +++ b/example/example.go @@ -9,10 +9,12 @@ import ( "io/ioutil" "net/http" "strings" + "time" "github.com/sirupsen/logrus" "go.linka.cloud/grpc/client" + "go.linka.cloud/grpc/logger" "go.linka.cloud/grpc/registry/mdns" "go.linka.cloud/grpc/service" ) @@ -39,6 +41,20 @@ func (g *GreeterHandler) SayHelloStream(req *HelloStreamRequest, s Greeter_SayHe return nil } +func httpLogger(next http.Handler) http.Handler { + return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + start := time.Now() + log := logger.From(request.Context()).WithFields( + "method", request.Method, + "host", request.Host, + "path", request.URL.Path, + "remoteAddress", request.RemoteAddr, + ) + next.ServeHTTP(writer, request) + log.WithField("duration", time.Since(start)).Info() + }) +} + func main() { name := "greeter" secure := true @@ -71,6 +87,7 @@ func main() { service.WithGatewayPrefix("/rest"), service.WithGRPCWeb(true), service.WithGRPCWebPrefix("/grpc"), + service.WithMiddlewares(httpLogger), ) if err != nil { panic(err) @@ -137,9 +154,8 @@ func main() { } logrus.Info(string(b)) } - do(scheme+address+"/rest/api/v1/greeter/hello", "application/json") + do(scheme+address+"/rest/api/v1/greeter/hello", "application/json") do(scheme+address+"/grpc/helloworld.Greeter/SayHello", "application/grpc-web+json") cancel() <-done } - diff --git a/go.mod b/go.mod index 66203ae..75c8995 100644 --- a/go.mod +++ b/go.mod @@ -13,9 +13,11 @@ require ( github.com/iancoleman/strcase v0.2.0 // indirect github.com/improbable-eng/grpc-web v0.14.1 github.com/jinzhu/gorm v1.9.12 + github.com/justinas/alice v1.2.0 github.com/lyft/protoc-gen-star v0.6.0 // indirect github.com/miekg/dns v1.1.35 github.com/planetscale/vtprotobuf v0.2.0 + github.com/rs/cors v1.7.0 github.com/sirupsen/logrus v1.8.1 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.0.0 diff --git a/go.sum b/go.sum index ffb049d..b44be89 100644 --- a/go.sum +++ b/go.sum @@ -368,6 +368,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= +github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= diff --git a/logger/logger.go b/logger/logger.go index 87de655..94eb479 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,6 +1,8 @@ package logger import ( + "fmt" + "github.com/sirupsen/logrus" ) @@ -14,7 +16,7 @@ func New() Logger { type Logger interface { WithField(key string, value interface{}) Logger - WithFields(kv ...string) Logger + WithFields(kv ...interface{}) Logger WithError(err error) Logger Debugf(format string, args ...interface{}) @@ -53,9 +55,9 @@ func (l *logger) WithField(key string, value interface{}) Logger { return &logger{FieldLogger: l.FieldLogger.WithField(key, value)} } -func (l *logger) WithFields(kv ...string) Logger { +func (l *logger) WithFields(kv ...interface{}) Logger { for i := 0; i < len(kv); i += 2 { - l.FieldLogger = l.FieldLogger.WithField(kv[i], kv[i+1]) + l.FieldLogger = l.FieldLogger.WithField(fmt.Sprintf("%v", kv[i]), kv[i+1]) } return l } diff --git a/service/gateway.go b/service/gateway.go index 428beeb..68dea35 100644 --- a/service/gateway.go +++ b/service/gateway.go @@ -21,9 +21,9 @@ func (s *service) gateway(opts ...runtime.ServeMuxOption) error { return err } if s.opts.gatewayPrefix != "" { - s.mux.Handle(s.opts.gatewayPrefix+"/", http.StripPrefix(s.opts.gatewayPrefix, mux)) + s.opts.mux.Handle(s.opts.gatewayPrefix+"/", http.StripPrefix(s.opts.gatewayPrefix, mux)) } else { - s.mux.Handle("/", mux) + s.opts.mux.Handle("/", mux) } return nil } diff --git a/service/mux.go b/service/mux.go new file mode 100644 index 0000000..1c7611b --- /dev/null +++ b/service/mux.go @@ -0,0 +1,15 @@ +package service + +import ( + "net/http" + + "github.com/justinas/alice" +) + +type ServeMux interface { + ServeHTTP(http.ResponseWriter, *http.Request) + Handle(pattern string, handler http.Handler) + HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) +} + +type Middleware = alice.Constructor diff --git a/service/options.go b/service/options.go index 6494a9b..193de65 100644 --- a/service/options.go +++ b/service/options.go @@ -83,8 +83,8 @@ type Options interface { ClientInterceptors() []grpc.UnaryClientInterceptor StreamClientInterceptors() []grpc.StreamClientInterceptor - Cors() cors.Options + Mux() ServeMux GRPCWeb() bool GRPCWebPrefix() string GRPCWebOpts() []grpcweb.Option @@ -266,6 +266,18 @@ func WithCors(opts cors.Options) Option { } } +func WithMux(mux ServeMux) Option { + return func(o *options) { + o.mux = mux + } +} + +func WithMiddlewares(m ...Middleware) Option { + return func(o *options) { + o.middlewares = m + } +} + func WithGRPCWeb(b bool) Option { return func(o *options) { o.grpcWeb = b @@ -334,11 +346,13 @@ type options struct { clientInterceptors []grpc.UnaryClientInterceptor streamClientInterceptors []grpc.StreamClientInterceptor + mux ServeMux + middlewares []Middleware grpcWeb bool grpcWebOpts []grpcweb.Option grpcWebPrefix string - gateway RegisterGatewayFunc - gatewayOpts []runtime.ServeMuxOption + gateway RegisterGatewayFunc + gatewayOpts []runtime.ServeMuxOption cors cors.Options error error @@ -433,6 +447,10 @@ func (o *options) Cors() cors.Options { return o.cors } +func (o *options) Mux() ServeMux { + return o.mux +} + func (o *options) GRPCWeb() bool { return o.grpcWeb } diff --git a/service/service.go b/service/service.go index c55a79d..7445137 100644 --- a/service/service.go +++ b/service/service.go @@ -18,6 +18,7 @@ import ( "github.com/google/uuid" grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" "github.com/jinzhu/gorm" + "github.com/justinas/alice" "github.com/rs/cors" "github.com/sirupsen/logrus" "github.com/soheilhy/cmux" @@ -54,7 +55,6 @@ type service struct { mu sync.Mutex running bool - mux *http.ServeMux // inproc Channel is used to serve grpc gateway inproc *inprocgrpc.Channel @@ -71,7 +71,6 @@ func newService(opts ...Option) (*service, error) { opts: parseFlags(NewOptions()), cmd: cmd, id: uuid.New().String(), - mux: http.NewServeMux(), inproc: &inprocgrpc.Channel{}, } s.mu.Lock() @@ -79,6 +78,9 @@ func newService(opts ...Option) (*service, error) { for _, f := range opts { f(s.opts) } + if s.opts.mux == nil { + s.opts.mux = http.NewServeMux() + } if s.opts.error != nil { return nil, s.opts.error } @@ -194,7 +196,7 @@ func (s *service) run() error { } } hServer := &http.Server{ - Handler: cors.New(s.opts.cors).Handler(s.mux), + Handler: alice.New(s.opts.middlewares...).Then(cors.New(s.opts.cors).Handler(s.opts.mux)), } if s.opts.Gateway() || s.opts.grpcWeb { go func() { diff --git a/service/web.go b/service/web.go index 7a69232..ee9aee3 100644 --- a/service/web.go +++ b/service/web.go @@ -26,9 +26,9 @@ func (s *service) grpcWeb(opts ...grpcweb.Option) error { h := grpcweb.WrapServer(s.server, append(defaultWebOptions, opts...)...) for _, v := range grpcweb.ListGRPCResources(s.server) { if s.opts.grpcWebPrefix != "" { - s.mux.Handle(s.opts.grpcWebPrefix+v, http.StripPrefix(s.opts.grpcWebPrefix, h)) + s.opts.mux.Handle(s.opts.grpcWebPrefix+v, http.StripPrefix(s.opts.grpcWebPrefix, h)) } else { - s.mux.Handle(v, h) + s.opts.mux.Handle(v, h) } } return nil