From 701c3e5242bd33b3b5035a9edc8a87c525f66f6d Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 1 Jul 2015 00:37:43 -0700 Subject: [PATCH] Add new RPC helpers wrapping over regular rpc packages, add middleware chaining ability --- pkg/server/router.go | 62 +++++++++++++++++++++++++++++++++------- pkg/server/rpc/server.go | 31 ++++++++++++++++---- pkg/server/server.go | 29 ++++--------------- 3 files changed, 83 insertions(+), 39 deletions(-) diff --git a/pkg/server/router.go b/pkg/server/router.go index 416f45da0..7c786f550 100644 --- a/pkg/server/router.go +++ b/pkg/server/router.go @@ -20,11 +20,11 @@ import ( "net/http" router "github.com/gorilla/mux" - jsonRPC "github.com/gorilla/rpc/v2" "github.com/minio/minio/pkg/server/api" "github.com/minio/minio/pkg/server/rpc" ) +// registerAPI - register all the object API handlers to their respective paths func registerAPI(mux *router.Router) http.Handler { api := api.MinioAPI{} @@ -50,28 +50,68 @@ func registerAPI(mux *router.Router) http.Handler { return mux } -func registerOthers(mux http.Handler, conf api.Config) http.Handler { - mux = api.ValidContentTypeHandler(mux) - mux = api.TimeValidityHandler(mux) - mux = api.IgnoreResourcesHandler(mux) - mux = api.ValidateAuthHeaderHandler(mux) +// add a handlerFunc typedef +type handlerFunc func(http.Handler) http.Handler + +// chain struct to hold handlers +type chain struct { + handlers []handlerFunc +} + +// loop through handlers and return a final one +func (c chain) final(mux http.Handler) http.Handler { + var f http.Handler + if mux != nil { + f = mux + } else { + f = http.DefaultServeMux + } + for _, handler := range c.handlers { + f = handler(f) + } + return f +} + +// registerChain - register an array of handlers in a chain of style -> handler(handler(handler(handler...))) +func registerChain(handlers ...handlerFunc) chain { + ch := chain{} + ch.handlers = append(ch.handlers, handlers...) + return ch +} + +// registerOtherMiddleware register all available middleware +func registerOtherMiddleware(mux http.Handler, conf api.Config) http.Handler { + ch := registerChain( + api.ValidContentTypeHandler, + api.TimeValidityHandler, + api.IgnoreResourcesHandler, + api.ValidateAuthHeaderHandler, + api.LoggingHandler, + // Add new middleware here + ) + + mux = ch.final(mux) mux = api.RateLimitHandler(mux, conf.RateLimit) - mux = api.LoggingHandler(mux) return mux } -func registerRPC(mux *router.Router, r *jsonRPC.Server) http.Handler { - mux.Handle("/rpc", r) +// registerRPC - register rpc handlers +func registerRPC(mux *router.Router, s *rpc.Server) http.Handler { + mux.Handle("/rpc", s) return mux } // APIHandler api handler func APIHandler(conf api.Config) http.Handler { mux := router.NewRouter() - return registerOthers(registerAPI(mux), conf) + return registerOtherMiddleware(registerAPI(mux), conf) } // RPCHandler rpc handler func RPCHandler() http.Handler { - return registerRPC(router.NewRouter(), rpc.HelloServiceHandler()) + s := rpc.NewServer() + s.RegisterJSONCodec() + s.RegisterService(new(rpc.HelloService), "") + // add more services here + return registerRPC(router.NewRouter(), s) } diff --git a/pkg/server/rpc/server.go b/pkg/server/rpc/server.go index 2b98b5213..935b91d96 100644 --- a/pkg/server/rpc/server.go +++ b/pkg/server/rpc/server.go @@ -17,14 +17,35 @@ package rpc import ( + "net/http" + "github.com/gorilla/rpc/v2" "github.com/gorilla/rpc/v2/json" ) -// HelloServiceHandler - -func HelloServiceHandler() *rpc.Server { - s := rpc.NewServer() - s.RegisterCodec(json.NewCodec(), "application/json") - s.RegisterService(new(HelloService), "") +// Server rpc server container +type Server struct { + RPCServer *rpc.Server +} + +// RegisterJSONCodec - register standard json codec +func (s Server) RegisterJSONCodec() { + s.RPCServer.RegisterCodec(json.NewCodec(), "application/json") +} + +// RegisterService - register new services +func (s Server) RegisterService(recv interface{}, name string) { + s.RPCServer.RegisterService(recv, name) +} + +// NewServer - provide a new instance of RPC server +func NewServer() *Server { + s := &Server{} + s.RPCServer = rpc.NewServer() return s } + +// ServeHTTP wrapper method for http.Handler interface +func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + s.RPCServer.ServeHTTP(w, r) +} diff --git a/pkg/server/server.go b/pkg/server/server.go index bf76caa06..83426d888 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -28,7 +28,6 @@ import ( func startAPI(errCh chan error, conf api.Config) { defer close(errCh) - var err error // Minio server config httpServer := &http.Server{ Addr: conf.Address, @@ -66,37 +65,26 @@ func startAPI(errCh chan error, conf api.Config) { for _, host := range hosts { fmt.Printf("Starting minio server on: http://%s:%s\n", host, port) } - err = httpServer.ListenAndServe() + errCh <- httpServer.ListenAndServe() case conf.TLS == true: for _, host := range hosts { fmt.Printf("Starting minio server on: https://%s:%s\n", host, port) } - err = httpServer.ListenAndServeTLS(conf.CertFile, conf.KeyFile) + errCh <- httpServer.ListenAndServeTLS(conf.CertFile, conf.KeyFile) } - if err != nil { - errCh <- err - } - errCh <- nil - return } func startRPC(errCh chan error) { defer close(errCh) rpcHandler := RPCHandler() - var err error // Minio server config httpServer := &http.Server{ - Addr: "127.0.0.1:9001", + Addr: "127.0.0.1:9001", // TODO make this configurable Handler: rpcHandler, MaxHeaderBytes: 1 << 20, } - err = httpServer.ListenAndServe() - if err != nil { - errCh <- err - } - errCh <- nil - return + errCh <- httpServer.ListenAndServe() } // StartServices starts basic services for a server @@ -109,13 +97,8 @@ func StartServices(conf api.Config) error { select { case err := <-apiErrCh: - if err != nil { - return err - } + return err case err := <-rpcErrCh: - if err != nil { - return err - } + return err } - return nil }