From 46eb11c6670fdaf98693f8d33fa21cc2606e9aa8 Mon Sep 17 00:00:00 2001 From: renaynay <41963722+renaynay@users.noreply.github.com> Date: Tue, 24 Mar 2020 21:28:18 +0100 Subject: [PATCH 1/4] handler stack creation moved from rpc to node pkg --- cmd/geth/retesteth.go | 131 +++++++++++++++++++++--------------------- node/node.go | 33 ++++++++++- rpc/endpoints.go | 51 +++++++++------- rpc/http.go | 13 ++++- 4 files changed, 137 insertions(+), 91 deletions(-) diff --git a/cmd/geth/retesteth.go b/cmd/geth/retesteth.go index c4013db422..098c42b1a9 100644 --- a/cmd/geth/retesteth.go +++ b/cmd/geth/retesteth.go @@ -21,8 +21,6 @@ import ( "context" "fmt" "math/big" - "os" - "os/signal" "strings" "time" @@ -40,7 +38,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -848,69 +845,69 @@ func splitAndTrim(input string) []string { return result } -func retesteth(ctx *cli.Context) error { - log.Info("Welcome to retesteth!") - // register signer API with server - var ( - extapiURL string - ) - apiImpl := &RetestethAPI{} - var testApi RetestethTestAPI = apiImpl - var ethApi RetestethEthAPI = apiImpl - var debugApi RetestethDebugAPI = apiImpl - var web3Api RetestWeb3API = apiImpl - rpcAPI := []rpc.API{ - { - Namespace: "test", - Public: true, - Service: testApi, - Version: "1.0", - }, - { - Namespace: "eth", - Public: true, - Service: ethApi, - Version: "1.0", - }, - { - Namespace: "debug", - Public: true, - Service: debugApi, - Version: "1.0", - }, - { - Namespace: "web3", - Public: true, - Service: web3Api, - Version: "1.0", - }, - } - vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name)) - cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name)) - - // start http server - var RetestethHTTPTimeouts = rpc.HTTPTimeouts{ - ReadTimeout: 120 * time.Second, - WriteTimeout: 120 * time.Second, - IdleTimeout: 120 * time.Second, - } - httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) - listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, RetestethHTTPTimeouts, []string{}) - if err != nil { - utils.Fatalf("Could not start RPC api: %v", err) - } - extapiURL = fmt.Sprintf("http://%s", httpEndpoint) - log.Info("HTTP endpoint opened", "url", extapiURL) - - defer func() { - listener.Close() - log.Info("HTTP endpoint closed", "url", httpEndpoint) - }() - - abortChan := make(chan os.Signal, 11) - signal.Notify(abortChan, os.Interrupt) - - sig := <-abortChan - log.Info("Exiting...", "signal", sig) +func retesteth(ctx *cli.Context) error { // TODO uncomment and fix test + //log.Info("Welcome to retesteth!") + //// register signer API with server + //var ( + // extapiURL string + //) + //apiImpl := &RetestethAPI{} + //var testApi RetestethTestAPI = apiImpl + //var ethApi RetestethEthAPI = apiImpl + //var debugApi RetestethDebugAPI = apiImpl + //var web3Api RetestWeb3API = apiImpl + //rpcAPI := []rpc.API{ + // { + // Namespace: "test", + // Public: true, + // Service: testApi, + // Version: "1.0", + // }, + // { + // Namespace: "eth", + // Public: true, + // Service: ethApi, + // Version: "1.0", + // }, + // { + // Namespace: "debug", + // Public: true, + // Service: debugApi, + // Version: "1.0", + // }, + // { + // Namespace: "web3", + // Public: true, + // Service: web3Api, + // Version: "1.0", + // }, + //} + //vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name)) + //cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name)) + // + //// start http server + //var RetestethHTTPTimeouts = rpc.HTTPTimeouts{ + // ReadTimeout: 120 * time.Second, + // WriteTimeout: 120 * time.Second, + // IdleTimeout: 120 * time.Second, + //} + //httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) + //listener, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, RetestethHTTPTimeouts, ) + //if err != nil { + // utils.Fatalf("Could not start RPC api: %v", err) + //} + //extapiURL = fmt.Sprintf("http://%s", httpEndpoint) + //log.Info("HTTP endpoint opened", "url", extapiURL) + // + //defer func() { + // listener.Close() + // log.Info("HTTP endpoint closed", "url", httpEndpoint) + //}() + // + //abortChan := make(chan os.Signal, 11) + //signal.Notify(abortChan, os.Interrupt) + // + //sig := <-abortChan + //log.Info("Exiting...", "signal", sig) return nil } diff --git a/node/node.go b/node/node.go index 41b4cc47db..4e75087a34 100644 --- a/node/node.go +++ b/node/node.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "net" + "net/http" "os" "path/filepath" "reflect" @@ -368,7 +369,29 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors if endpoint == "" { return nil } - listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts, wsOrigins) + + srv := rpc.NewServer() + + // TODO put this stuff in a separate function + // Generate the whitelist based on the allowed modules + whitelist := make(map[string]bool) + for _, module := range modules { + whitelist[module] = true + } + // Register all the APIs exposed by the services + for _, api := range apis { + if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { + if err := srv.RegisterName(api.Namespace, api.Service); err != nil { + return err + } + log.Debug("HTTP registered", "namespace", api.Namespace) + } + } + + // create handler stack + handler := n.CreateHandler(srv, cors, vhosts, wsOrigins) + + listener, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, timeouts, handler) if err != nil { return err } @@ -383,11 +406,17 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors // All listeners booted successfully n.httpEndpoint = endpoint n.httpListener = listener - n.httpHandler = handler + n.httpHandler = srv return nil } +// CreateHandler creates the handler stack necessary to handle both http rpc requests and websocket requests +func (n *Node) CreateHandler(srv *rpc.Server, cors []string, vhosts []string, wsOrigins []string) http.Handler { + handler := rpc.NewHTTPHandlerStack(srv, cors, vhosts) + return rpc.NewWebsocketUpgradeHandler(handler, srv.WebsocketHandler(wsOrigins)) +} + // stopHTTP terminates the HTTP RPC endpoint. func (n *Node) stopHTTP() { if n.httpListener != nil { diff --git a/rpc/endpoints.go b/rpc/endpoints.go index 4a0ded76db..30fbbb0033 100644 --- a/rpc/endpoints.go +++ b/rpc/endpoints.go @@ -18,6 +18,8 @@ package rpc import ( "net" + "net/http" + "time" "github.com/ethereum/go-ethereum/log" ) @@ -42,37 +44,46 @@ func checkModuleAvailability(modules []string, apis []API) (bad, available []str } // StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules. -func StartHTTPEndpoint(endpoint string, apis []API, modules []string, cors []string, vhosts []string, timeouts HTTPTimeouts, wsOrigins []string) (net.Listener, *Server, error) { +func StartHTTPEndpoint(endpoint string, apis []API, modules []string, timeouts HTTPTimeouts, handler http.Handler) (net.Listener, error) { if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 { log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available) } - // Generate the whitelist based on the allowed modules - whitelist := make(map[string]bool) - for _, module := range modules { - whitelist[module] = true - } - // Register all the APIs exposed by the services - handler := NewServer() - for _, api := range apis { - if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { - if err := handler.RegisterName(api.Namespace, api.Service); err != nil { - return nil, nil, err - } - log.Debug("HTTP registered", "namespace", api.Namespace) - } - } - // All APIs registered, start the HTTP listener + + // Start the HTTP listener var ( listener net.Listener err error ) if listener, err = net.Listen("tcp", endpoint); err != nil { - return nil, nil, err + return nil, err } + // TODO put timeout registration in separate function + // Make sure timeout values are meaningful + if timeouts.ReadTimeout < time.Second { + log.Warn("Sanitizing invalid HTTP read timeout", "provided", timeouts.ReadTimeout, "updated", DefaultHTTPTimeouts.ReadTimeout) + timeouts.ReadTimeout = DefaultHTTPTimeouts.ReadTimeout + } + if timeouts.WriteTimeout < time.Second { + log.Warn("Sanitizing invalid HTTP write timeout", "provided", timeouts.WriteTimeout, "updated", DefaultHTTPTimeouts.WriteTimeout) + timeouts.WriteTimeout = DefaultHTTPTimeouts.WriteTimeout + } + if timeouts.IdleTimeout < time.Second { + log.Warn("Sanitizing invalid HTTP idle timeout", "provided", timeouts.IdleTimeout, "updated", DefaultHTTPTimeouts.IdleTimeout) + timeouts.IdleTimeout = DefaultHTTPTimeouts.IdleTimeout + } - go NewHTTPServer(cors, vhosts, timeouts, handler, handler.WebsocketHandler(wsOrigins)).Serve(listener) - return listener, handler, err + // Bundle and start the HTTP server + httpSrv := &http.Server{ + Handler: handler, + ReadTimeout: timeouts.ReadTimeout, + WriteTimeout: timeouts.WriteTimeout, + IdleTimeout: timeouts.IdleTimeout, + } + + go httpSrv.Serve(listener) + // go NewHTTPServer(cors, vhosts, timeouts, handler, handler.WebsocketHandler(wsOrigins)).Serve(listener) // TODO REMOVE + return listener, err } // StartWSEndpoint starts a websocket endpoint. diff --git a/rpc/http.go b/rpc/http.go index 439029d44b..3e5892c9a7 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -217,7 +217,7 @@ func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv ht handler := newCorsHandler(srv, cors) handler = newVHostHandler(vhosts, handler) handler = newGzipHandler(handler) - handler = newWebsocketUpgradeHandler(handler, ws) + handler = NewWebsocketUpgradeHandler(handler, ws) // Make sure timeout values are meaningful if timeouts.ReadTimeout < time.Second { @@ -298,6 +298,14 @@ func validateRequest(r *http.Request) (int, error) { return http.StatusUnsupportedMediaType, err } +// NewHTTPHandlerStack TODO document +func NewHTTPHandlerStack(srv *Server, cors []string, vhosts []string) http.Handler { + // Wrap the CORS-handler within a host-handler + handler := newCorsHandler(srv, cors) + handler = newVHostHandler(vhosts, handler) + return newGzipHandler(handler) +} + func newCorsHandler(srv http.Handler, allowedOrigins []string) http.Handler { // disable CORS support if user has not specified a custom CORS configuration if len(allowedOrigins) == 0 { @@ -359,10 +367,11 @@ func newVHostHandler(vhosts []string, next http.Handler) http.Handler { return &virtualHostHandler{vhostMap, next} } -func newWebsocketUpgradeHandler(h http.Handler, ws http.Handler) http.Handler { +func NewWebsocketUpgradeHandler(h http.Handler, ws http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if isWebsocket(r) { ws.ServeHTTP(w, r) + log.Debug("serving websocket request") return } From 62bb958471ef9c24d57e312c4d667f4f9ea4290d Mon Sep 17 00:00:00 2001 From: renaynay <41963722+renaynay@users.noreply.github.com> Date: Tue, 24 Mar 2020 21:37:48 +0100 Subject: [PATCH 2/4] fixed retesteth --- cmd/geth/retesteth.go | 135 ++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 63 deletions(-) diff --git a/cmd/geth/retesteth.go b/cmd/geth/retesteth.go index 098c42b1a9..c5286d4355 100644 --- a/cmd/geth/retesteth.go +++ b/cmd/geth/retesteth.go @@ -21,6 +21,8 @@ import ( "context" "fmt" "math/big" + "os" + "os/signal" "strings" "time" @@ -38,6 +40,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -846,68 +849,74 @@ func splitAndTrim(input string) []string { } func retesteth(ctx *cli.Context) error { // TODO uncomment and fix test - //log.Info("Welcome to retesteth!") - //// register signer API with server - //var ( - // extapiURL string - //) - //apiImpl := &RetestethAPI{} - //var testApi RetestethTestAPI = apiImpl - //var ethApi RetestethEthAPI = apiImpl - //var debugApi RetestethDebugAPI = apiImpl - //var web3Api RetestWeb3API = apiImpl - //rpcAPI := []rpc.API{ - // { - // Namespace: "test", - // Public: true, - // Service: testApi, - // Version: "1.0", - // }, - // { - // Namespace: "eth", - // Public: true, - // Service: ethApi, - // Version: "1.0", - // }, - // { - // Namespace: "debug", - // Public: true, - // Service: debugApi, - // Version: "1.0", - // }, - // { - // Namespace: "web3", - // Public: true, - // Service: web3Api, - // Version: "1.0", - // }, - //} - //vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name)) - //cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name)) - // - //// start http server - //var RetestethHTTPTimeouts = rpc.HTTPTimeouts{ - // ReadTimeout: 120 * time.Second, - // WriteTimeout: 120 * time.Second, - // IdleTimeout: 120 * time.Second, - //} - //httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) - //listener, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, RetestethHTTPTimeouts, ) - //if err != nil { - // utils.Fatalf("Could not start RPC api: %v", err) - //} - //extapiURL = fmt.Sprintf("http://%s", httpEndpoint) - //log.Info("HTTP endpoint opened", "url", extapiURL) - // - //defer func() { - // listener.Close() - // log.Info("HTTP endpoint closed", "url", httpEndpoint) - //}() - // - //abortChan := make(chan os.Signal, 11) - //signal.Notify(abortChan, os.Interrupt) - // - //sig := <-abortChan - //log.Info("Exiting...", "signal", sig) + log.Info("Welcome to retesteth!") + // register signer API with server + var ( + extapiURL string + ) + apiImpl := &RetestethAPI{} + var testApi RetestethTestAPI = apiImpl + var ethApi RetestethEthAPI = apiImpl + var debugApi RetestethDebugAPI = apiImpl + var web3Api RetestWeb3API = apiImpl + rpcAPI := []rpc.API{ + { + Namespace: "test", + Public: true, + Service: testApi, + Version: "1.0", + }, + { + Namespace: "eth", + Public: true, + Service: ethApi, + Version: "1.0", + }, + { + Namespace: "debug", + Public: true, + Service: debugApi, + Version: "1.0", + }, + { + Namespace: "web3", + Public: true, + Service: web3Api, + Version: "1.0", + }, + } + vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name)) + cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name)) + wsOrigins := splitAndTrim(ctx.GlobalString(utils.WSAllowedOriginsFlag.Value)) + + srv := rpc.NewServer() + + handler := rpc.NewHTTPHandlerStack(srv, cors, vhosts) + handler = rpc.NewWebsocketUpgradeHandler(handler, srv.WebsocketHandler(wsOrigins)) + + // start http server + var RetestethHTTPTimeouts = rpc.HTTPTimeouts{ + ReadTimeout: 120 * time.Second, + WriteTimeout: 120 * time.Second, + IdleTimeout: 120 * time.Second, + } + httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) + listener, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, RetestethHTTPTimeouts, handler) + if err != nil { + utils.Fatalf("Could not start RPC api: %v", err) + } + extapiURL = fmt.Sprintf("http://%s", httpEndpoint) + log.Info("HTTP endpoint opened", "url", extapiURL) + + defer func() { + listener.Close() + log.Info("HTTP endpoint closed", "url", httpEndpoint) + }() + + abortChan := make(chan os.Signal, 11) + signal.Notify(abortChan, os.Interrupt) + + sig := <-abortChan + log.Info("Exiting...", "signal", sig) return nil } From fdff70c14cd455f8995262bd2e13faa1a3ada514 Mon Sep 17 00:00:00 2001 From: renaynay <41963722+renaynay@users.noreply.github.com> Date: Tue, 24 Mar 2020 21:48:00 +0100 Subject: [PATCH 3/4] fixed some TODOs --- cmd/geth/retesteth.go | 2 +- node/node.go | 2 +- rpc/endpoints.go | 2 -- rpc/http.go | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmd/geth/retesteth.go b/cmd/geth/retesteth.go index c5286d4355..43cb8191fb 100644 --- a/cmd/geth/retesteth.go +++ b/cmd/geth/retesteth.go @@ -848,7 +848,7 @@ func splitAndTrim(input string) []string { return result } -func retesteth(ctx *cli.Context) error { // TODO uncomment and fix test +func retesteth(ctx *cli.Context) error { log.Info("Welcome to retesteth!") // register signer API with server var ( diff --git a/node/node.go b/node/node.go index 4e75087a34..14a53d24ed 100644 --- a/node/node.go +++ b/node/node.go @@ -372,12 +372,12 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors srv := rpc.NewServer() - // TODO put this stuff in a separate function // Generate the whitelist based on the allowed modules whitelist := make(map[string]bool) for _, module := range modules { whitelist[module] = true } + // Register all the APIs exposed by the services for _, api := range apis { if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { diff --git a/rpc/endpoints.go b/rpc/endpoints.go index 30fbbb0033..a749735b47 100644 --- a/rpc/endpoints.go +++ b/rpc/endpoints.go @@ -58,7 +58,6 @@ func StartHTTPEndpoint(endpoint string, apis []API, modules []string, timeouts H return nil, err } - // TODO put timeout registration in separate function // Make sure timeout values are meaningful if timeouts.ReadTimeout < time.Second { log.Warn("Sanitizing invalid HTTP read timeout", "provided", timeouts.ReadTimeout, "updated", DefaultHTTPTimeouts.ReadTimeout) @@ -82,7 +81,6 @@ func StartHTTPEndpoint(endpoint string, apis []API, modules []string, timeouts H } go httpSrv.Serve(listener) - // go NewHTTPServer(cors, vhosts, timeouts, handler, handler.WebsocketHandler(wsOrigins)).Serve(listener) // TODO REMOVE return listener, err } diff --git a/rpc/http.go b/rpc/http.go index 3e5892c9a7..5ac3c689cf 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -298,7 +298,7 @@ func validateRequest(r *http.Request) (int, error) { return http.StatusUnsupportedMediaType, err } -// NewHTTPHandlerStack TODO document +// NewHTTPHandlerStack returns wrapped http-related handlers func NewHTTPHandlerStack(srv *Server, cors []string, vhosts []string) http.Handler { // Wrap the CORS-handler within a host-handler handler := newCorsHandler(srv, cors) From 5eb01467744071e2913f6635ee092951694811c1 Mon Sep 17 00:00:00 2001 From: renaynay <41963722+renaynay@users.noreply.github.com> Date: Tue, 24 Mar 2020 22:20:05 +0100 Subject: [PATCH 4/4] moved whitelist generation and api registration into separate method --- node/node.go | 54 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/node/node.go b/node/node.go index 14a53d24ed..52ac182ca7 100644 --- a/node/node.go +++ b/node/node.go @@ -372,24 +372,15 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors srv := rpc.NewServer() - // Generate the whitelist based on the allowed modules - whitelist := make(map[string]bool) - for _, module := range modules { - whitelist[module] = true + err := RegisterApisFromWhitelist(apis, modules, srv) + + var ws http.Handler + if n.httpEndpoint == n.wsEndpoint { + ws = srv.WebsocketHandler(wsOrigins) } - // Register all the APIs exposed by the services - for _, api := range apis { - if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { - if err := srv.RegisterName(api.Namespace, api.Service); err != nil { - return err - } - log.Debug("HTTP registered", "namespace", api.Namespace) - } - } - - // create handler stack - handler := n.CreateHandler(srv, cors, vhosts, wsOrigins) + // wrap handler in websocket handler only if websocket port is the same as http rpc + handler := n.AddWebsocketHandler(rpc.NewHTTPHandlerStack(srv, cors, vhosts), ws) listener, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, timeouts, handler) if err != nil { @@ -411,10 +402,13 @@ func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors return nil } -// CreateHandler creates the handler stack necessary to handle both http rpc requests and websocket requests -func (n *Node) CreateHandler(srv *rpc.Server, cors []string, vhosts []string, wsOrigins []string) http.Handler { - handler := rpc.NewHTTPHandlerStack(srv, cors, vhosts) - return rpc.NewWebsocketUpgradeHandler(handler, srv.WebsocketHandler(wsOrigins)) +// AddWebsocketHandler creates the handler stack necessary to handle both http rpc requests and websocket requests +func (n *Node) AddWebsocketHandler(handler http.Handler, websocket http.Handler) http.Handler { + if websocket != nil { + return rpc.NewWebsocketUpgradeHandler(handler, websocket) + } + + return handler } // stopHTTP terminates the HTTP RPC endpoint. @@ -702,3 +696,23 @@ func (n *Node) apis() []rpc.API { }, } } + +func RegisterApisFromWhitelist(apis []rpc.API, modules []string, srv *rpc.Server) error { + // Generate the whitelist based on the allowed modules + whitelist := make(map[string]bool) + for _, module := range modules { + whitelist[module] = true + } + + // Register all the APIs exposed by the services + for _, api := range apis { + if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) { + if err := srv.RegisterName(api.Namespace, api.Service); err != nil { + return err + } + log.Debug("HTTP registered", "namespace", api.Namespace) + } + } + + return nil +}