From 4c3d3058f63b005c787a53163a368a174f9488cf Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sun, 18 Jun 2023 17:28:29 +0300 Subject: [PATCH 1/2] handler/swagger: initial import Signed-off-by: Vasiliy Tolstov --- handler/swagger/swagger.go | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 handler/swagger/swagger.go diff --git a/handler/swagger/swagger.go b/handler/swagger/swagger.go new file mode 100644 index 0000000..df85a63 --- /dev/null +++ b/handler/swagger/swagger.go @@ -0,0 +1,55 @@ +package swagger + +import ( + "io/fs" + "net/http" + + yamlcodec "go.unistack.org/micro-codec-yaml/v3" + rutil "go.unistack.org/micro/v3/util/reflect" +) + +// Handler append to generated swagger data from dst map[string]interface{} +var Handler = func(dst map[string]interface{}, fsys fs.FS) http.HandlerFunc { + c := yamlcodec.NewCodec() + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusNotFound) + return + } + + path := r.URL.Path + if len(path) > 1 && path[0] == '/' { + path = path[1:] + } + + buf, err := fs.ReadFile(fsys, path) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(err.Error())) + return + } + + var src interface{} + + if err = c.Unmarshal(buf, src); err != nil { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(err.Error())) + return + } + + if err = rutil.Merge(src, dst); err != nil { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(err.Error())) + return + } + + if buf, err = c.Marshal(src); err != nil { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(err.Error())) + return + } + + w.WriteHeader(http.StatusOK) + _, _ = w.Write(buf) + } +} From 7e850f75e095732adea270727b18260810ebe3db Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sat, 12 Aug 2023 13:53:04 +0300 Subject: [PATCH 2/2] update for latest micro changes Signed-off-by: Vasiliy Tolstov --- go.mod | 9 +++++--- go.sum | 22 ++++++++++++------- handler.go | 20 +++++++++--------- handler/swagger/swagger.go | 4 ++-- http.go | 43 +++++++++++++++++++++----------------- options.go | 43 ++++++++++++++++++++++---------------- 6 files changed, 82 insertions(+), 59 deletions(-) diff --git a/go.mod b/go.mod index f3c7063..2b79a1c 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,17 @@ module go.unistack.org/micro-server-http/v4 go 1.19 require ( + go.unistack.org/micro-codec-yaml/v4 v4.0.0 go.unistack.org/micro-proto/v4 v4.0.0 - go.unistack.org/micro/v4 v4.0.1 + go.unistack.org/micro/v4 v4.0.6 golang.org/x/net v0.7.0 ) require ( - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect - google.golang.org/protobuf v1.28.1 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 8e7c920..cce4c46 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -35,8 +36,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -48,11 +50,11 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -65,10 +67,12 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.unistack.org/micro-codec-yaml/v4 v4.0.0 h1:DK/+fA69gmnvYmGHe3kqVR0pukS8ank5lPG4MfdPQEk= +go.unistack.org/micro-codec-yaml/v4 v4.0.0/go.mod h1:UG4ouILbUfgNL7nvp7CpmD2IIzO8bQHjzDIahOvIAgM= go.unistack.org/micro-proto/v4 v4.0.0 h1:+TAwKSlx48eLsNO2E2cO0JLE8we1KU2AuWe9Q310FuU= go.unistack.org/micro-proto/v4 v4.0.0/go.mod h1:ArmK7o+uFvxSY3dbJhKBBX4Pm1rhWdLEFf3LxBrMtec= -go.unistack.org/micro/v4 v4.0.1 h1:xo1IxbVfgh8i0eY0VeYa3cbb13u5n/Mxnp3FOgWD4Jo= -go.unistack.org/micro/v4 v4.0.1/go.mod h1:p/J5UcSJjfHsWGT31uKoghQ5rUQZzQJBAFy+Z4+ZVMs= +go.unistack.org/micro/v4 v4.0.6 h1:YFWvTh3VwyOd6NHYTQcf47n2TF5+p/EhpnbuBQX3qhk= +go.unistack.org/micro/v4 v4.0.6/go.mod h1:bVEYTlPi0EsdgZZt311bIroDg9ict7ky3C87dSCCAGk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -139,15 +143,19 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/handler.go b/handler.go index 3f01bd6..078dccd 100644 --- a/handler.go +++ b/handler.go @@ -19,7 +19,7 @@ import ( ) var ( - DefaultErrorHandler = func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int) { + DefaultErrorHandler = func(ctx context.Context, s interface{}, w http.ResponseWriter, r *http.Request, err error, status int) { w.WriteHeader(status) if _, cerr := w.Write([]byte(err.Error())); cerr != nil { logger.DefaultLogger.Errorf(ctx, "write failed: %v", cerr) @@ -35,7 +35,7 @@ type patHandler struct { } type httpHandler struct { - opts server.HandlerOptions + opts server.HandleOptions hd interface{} handlers *rhttp.Trie name string @@ -56,7 +56,7 @@ func (h *httpHandler) Endpoints() []*register.Endpoint { return h.eps } -func (h *httpHandler) Options() server.HandlerOptions { +func (h *httpHandler) Options() server.HandleOptions { return h.opts } @@ -266,9 +266,9 @@ func (h *Server) HTTPHandlerFunc(handler interface{}) (http.HandlerFunc, error) } // wrap the handler func - for i := len(handler.sopts.HdlrWrappers); i > 0; i-- { - fn = handler.sopts.HdlrWrappers[i-1](fn) - } + // for i := len(handler.sopts.Hooks); i > 0; i-- { + // fn = handler.sopts.Hooks[i-1](fn) + // } if ct == "application/x-www-form-urlencoded" { cf, err = h.newCodec(DefaultContentType) @@ -416,7 +416,7 @@ func (h *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if !match && h.hd != nil { - if hdlr, ok := h.hd.Handler().(http.Handler); ok { + if hdlr, ok := h.hd.(http.Handler); ok { hdlr.ServeHTTP(w, r) return } @@ -529,9 +529,9 @@ func (h *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // wrap the handler func - for i := len(handler.sopts.HdlrWrappers); i > 0; i-- { - fn = handler.sopts.HdlrWrappers[i-1](fn) - } + // for i := len(handler.sopts.HdlrWrappers); i > 0; i-- { + // fn = handler.sopts.HdlrWrappers[i-1](fn) + // } if ct == "application/x-www-form-urlencoded" { cf, err = h.newCodec(DefaultContentType) diff --git a/handler/swagger/swagger.go b/handler/swagger/swagger.go index df85a63..b1d680c 100644 --- a/handler/swagger/swagger.go +++ b/handler/swagger/swagger.go @@ -4,8 +4,8 @@ import ( "io/fs" "net/http" - yamlcodec "go.unistack.org/micro-codec-yaml/v3" - rutil "go.unistack.org/micro/v3/util/reflect" + yamlcodec "go.unistack.org/micro-codec-yaml/v4" + rutil "go.unistack.org/micro/v4/util/reflect" ) // Handler append to generated swagger data from dst map[string]interface{} diff --git a/http.go b/http.go index e0152a7..75d2486 100644 --- a/http.go +++ b/http.go @@ -15,6 +15,7 @@ import ( "go.unistack.org/micro/v4/codec" "go.unistack.org/micro/v4/logger" + "go.unistack.org/micro/v4/options" "go.unistack.org/micro/v4/register" "go.unistack.org/micro/v4/server" rhttp "go.unistack.org/micro/v4/util/http" @@ -24,11 +25,11 @@ import ( var _ server.Server = (*Server)(nil) type Server struct { - hd server.Handler + hd interface{} rsvc *register.Service - handlers map[string]server.Handler + handlers map[string]interface{} exit chan chan error - errorHandler func(context.Context, server.Handler, http.ResponseWriter, *http.Request, error, int) + errorHandler func(context.Context, interface{}, http.ResponseWriter, *http.Request, error, int) pathHandlers *rhttp.Trie opts server.Options registerRPC bool @@ -57,7 +58,7 @@ func (h *Server) Options() server.Options { return opts } -func (h *Server) Init(opts ...server.Option) error { +func (h *Server) Init(opts ...options.Option) error { if len(opts) == 0 && h.init { return nil } @@ -67,11 +68,11 @@ func (h *Server) Init(opts ...server.Option) error { for _, o := range opts { o(&h.opts) } - if fn, ok := h.opts.Context.Value(errorHandlerKey{}).(func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int)); ok && fn != nil { + if fn, ok := h.opts.Context.Value(errorHandlerKey{}).(func(ctx context.Context, s interface{}, w http.ResponseWriter, r *http.Request, err error, status int)); ok && fn != nil { h.errorHandler = fn } if h.handlers == nil { - h.handlers = make(map[string]server.Handler) + h.handlers = make(map[string]interface{}) } if h.pathHandlers == nil { h.pathHandlers = rhttp.NewTrie() @@ -110,10 +111,6 @@ func (h *Server) Init(opts ...server.Option) error { h.RUnlock() return err } - if err := h.opts.Transport.Init(); err != nil { - h.RUnlock() - return err - } h.RUnlock() h.Lock() @@ -123,7 +120,9 @@ func (h *Server) Init(opts ...server.Option) error { return nil } -func (h *Server) Handle(handler server.Handler) error { +func (h *Server) Handle(handler interface{}, opts ...options.Option) error { + options := server.NewHandleOptions(opts...) + // passed unknown handler hdlr, ok := handler.(*httpHandler) if !ok { @@ -144,16 +143,18 @@ func (h *Server) Handle(handler server.Handler) error { // passed micro compat handler h.Lock() if h.handlers == nil { - h.handlers = make(map[string]server.Handler) + h.handlers = make(map[string]interface{}) + } + for k := range options.Metadata { + h.handlers[k] = handler } - h.handlers[handler.Name()] = handler h.Unlock() return nil } -func (h *Server) NewHandler(handler interface{}, opts ...server.HandlerOption) server.Handler { - options := server.NewHandlerOptions(opts...) +func (h *Server) newHTTPHandler(handler interface{}, opts ...options.Option) *httpHandler { + options := server.NewHandleOptions(opts...) eps := make([]*register.Endpoint, 0, len(options.Metadata)) for name, metadata := range options.Metadata { @@ -285,7 +286,11 @@ func (h *Server) Register() error { var eps []*register.Endpoint h.RLock() for _, hdlr := range h.handlers { - eps = append(eps, hdlr.Endpoints()...) + hd, ok := hdlr.(*httpHandler) + if !ok { + continue + } + eps = append(eps, hd.Endpoints()...) } rsvc := h.rsvc config := h.opts @@ -409,7 +414,7 @@ func (h *Server) Start() error { if h.opts.Context != nil { if hs, ok := h.opts.Context.Value(serverKey{}).(*http.Server); ok && hs != nil { if hs.Handler == nil && h.hd != nil { - if hdlr, ok := h.hd.Handler().(http.Handler); ok { + if hdlr, ok := h.hd.(http.Handler); ok { hs.Handler = hdlr handler = hs.Handler } @@ -425,7 +430,7 @@ func (h *Server) Start() error { case len(h.handlers) > 0 && h.hd != nil: handler = h case handler == nil && h.hd != nil: - if hdlr, ok := h.hd.Handler().(http.Handler); ok { + if hdlr, ok := h.hd.(http.Handler); ok { handler = hdlr } } @@ -551,7 +556,7 @@ func (h *Server) Name() string { return h.opts.Name } -func NewServer(opts ...server.Option) *Server { +func NewServer(opts ...options.Option) *Server { options := server.NewOptions(opts...) eh := DefaultErrorHandler if v, ok := options.Context.Value(errorHandlerKey{}).(errorHandler); ok && v != nil { diff --git a/options.go b/options.go index fa3da2f..1ce3695 100644 --- a/options.go +++ b/options.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "go.unistack.org/micro/v4/server" + "go.unistack.org/micro/v4/options" ) // SetError pass error to caller @@ -79,24 +79,24 @@ func GetRspCode(ctx context.Context) int { type middlewareKey struct{} // Middleware passes http middlewares -func Middleware(mw ...func(http.Handler) http.Handler) server.Option { - return server.SetOption(middlewareKey{}, mw) +func Middleware(mw ...func(http.Handler) http.Handler) options.Option { + return options.ContextOption(middlewareKey{}, mw) } type serverKey struct{} // HTTPServer provide ability to pass *http.Server -func HTTPServer(hs *http.Server) server.Option { - return server.SetOption(serverKey{}, hs) +func HTTPServer(hs *http.Server) options.Option { + return options.ContextOption(serverKey{}, hs) } -type errorHandler func(ctx context.Context, s server.Handler, w http.ResponseWriter, r *http.Request, err error, status int) +type errorHandler func(ctx context.Context, s interface{}, w http.ResponseWriter, r *http.Request, err error, status int) type errorHandlerKey struct{} // ErrorHandler specifies handler for errors -func ErrorHandler(fn errorHandler) server.Option { - return server.SetOption(errorHandlerKey{}, fn) +func ErrorHandler(fn errorHandler) options.Option { + return options.ContextOption(errorHandlerKey{}, fn) } type ( @@ -107,12 +107,18 @@ type ( ) // PathHandler specifies http handler for path regexp -func PathHandler(method, path string, handler http.HandlerFunc) server.Option { - return func(o *server.Options) { - if o.Context == nil { - o.Context = context.Background() +func PathHandler(method, path string, handler http.HandlerFunc) options.Option { + return func(src interface{}) error { + vctx, err := options.Get(src, ".Context") + if err != nil { + return err } - v, ok := o.Context.Value(pathHandlerKey{}).(*pathHandlerVal) + ctx, ok := vctx.(context.Context) + if !ok { + return fmt.Errorf("invalid option") + } + + v, ok := ctx.Value(pathHandlerKey{}).(*pathHandlerVal) if !ok { v = &pathHandlerVal{h: make(map[string]map[string]http.HandlerFunc)} } @@ -121,16 +127,17 @@ func PathHandler(method, path string, handler http.HandlerFunc) server.Option { m = make(map[string]http.HandlerFunc) v.h[method] = m } + ctx = context.WithValue(ctx, pathHandlerKey{}, v) m[path] = handler - o.Context = context.WithValue(o.Context, pathHandlerKey{}, v) + return options.Set(src, ctx, ".Context") } } type registerRPCHandlerKey struct{} // RegisterRPCHandler registers compatibility endpoints with /ServiceName.ServiceEndpoint method POST -func RegisterRPCHandler(b bool) server.Option { - return server.SetOption(registerRPCHandlerKey{}, b) +func RegisterRPCHandler(b bool) options.Option { + return options.ContextOption(registerRPCHandlerKey{}, b) } type handlerEndpointsKey struct{} @@ -143,8 +150,8 @@ type EndpointMetadata struct { Stream bool } -func HandlerEndpoints(md []EndpointMetadata) server.HandlerOption { - return server.SetHandlerOption(handlerEndpointsKey{}, md) +func HandlerEndpoints(md []EndpointMetadata) options.Option { + return options.ContextOption(handlerEndpointsKey{}, md) } type handlerOptions struct {