From 68c4d9a0305020b176089a6cff42b5ccf54689cf Mon Sep 17 00:00:00 2001 From: Andrew Martinez Date: Wed, 5 May 2021 14:09:23 -0400 Subject: [PATCH] fixes xweb comments, fixes xweb startup - fixes multi server startup would block on first server - fixes comments, goland was complaining - adds better output for what APIs are starting on what servers/bind points - adds IsHandled() demuxer --- controller/xweb/config.go | 59 +++++++++++++++++----------------- controller/xweb/contextutil.go | 8 ++--- controller/xweb/demux.go | 49 +++++++++++++++++++++++----- controller/xweb/registry.go | 27 ++++++++-------- controller/xweb/server.go | 42 +++++++++++++++--------- controller/xweb/web.go | 32 +++++++++--------- 6 files changed, 132 insertions(+), 85 deletions(-) diff --git a/controller/xweb/config.go b/controller/xweb/config.go index c79872600..570e66ec9 100644 --- a/controller/xweb/config.go +++ b/controller/xweb/config.go @@ -24,7 +24,7 @@ import ( "time" ) -// The root configuration options necessary to start numerous http.Server instances via WebListener's. +// Config is the root configuration options necessary to start numerous http.Server instances via WebListener's. type Config struct { WebListeners []*WebListener DefaultIdentityConfig *identity.IdentityConfig @@ -35,7 +35,7 @@ type Config struct { enabled bool } -// Parses a configuration map, looking for sections that define an identity.IdentityConfig and an array of WebListener's. +// Parse parses a configuration map, looking for sections that define an identity.IdentityConfig and an array of WebListener's. func (config *Config) Parse(configMap map[interface{}]interface{}) error { if config.DefaultIdentitySection == "" { @@ -87,8 +87,8 @@ func (config *Config) Parse(configMap map[interface{}]interface{}) error { return nil } -// Uses a WebHandlerFactoryRegistry to validate that all API bindings may be fulfilled. All other relevant Config values -// are also validated. +// Validate uses a WebHandlerFactoryRegistry to validate that all API bindings may be fulfilled. All other relevant +// Config values are also validated. func (config *Config) Validate(registry WebHandlerFactoryRegistry) error { //validate default identity by loading @@ -116,13 +116,14 @@ func (config *Config) Validate(registry WebHandlerFactoryRegistry) error { return nil } -// Whether this configuration should be considered "enabled". Set to true after Validate passes. +// Enabled returns true/false on whether this configuration should be considered "enabled". Set to true after +// Validate passes. func (config *Config) Enabled() bool { return config.enabled } -// The configuration that will eventually be used to create an xweb.Server (which in turn houses all of the components -// necessary to run multiple http.Server's). +// WebListener is the configuration that will eventually be used to create an xweb.Server (which in turn houses all +// of the components necessary to run multiple http.Server's). type WebListener struct { Name string APIs []*API @@ -136,7 +137,7 @@ type WebListener struct { DefaultIdentity identity.Identity } -// Parses a configuration map to set all relavant WebListener values. +// Parse parses a configuration map to set all relevant WebListener values. func (web *WebListener) Parse(webConfigMap map[interface{}]interface{}) error { //parse name, required, string if nameInterface, ok := webConfigMap["name"]; ok { @@ -223,7 +224,7 @@ func (web *WebListener) Parse(webConfigMap map[interface{}]interface{}) error { return nil } -// Validates all WebListener values +// Validate all WebListener values func (web *WebListener) Validate(registry WebHandlerFactoryRegistry) error { if web.Name == "" { return errors.New("name must not be empty") @@ -284,7 +285,7 @@ func (web *WebListener) Validate(registry WebHandlerFactoryRegistry) error { } -// Represents some "api" or "site" by binding name. Each API configuration is used against a WebHandlerFactoryRegistry +// API represents some "api" or "site" by binding name. Each API configuration is used against a WebHandlerFactoryRegistry // to locate the proper factory to generate a WebHandler. The options provided by this structure are parsed by the // WebHandlerFactory and the behavior, valid keys, and valid values are not defined by xweb components, but by that // WebHandlerFactory and it resulting WebHandler's. @@ -293,18 +294,18 @@ type API struct { options map[interface{}]interface{} } -// Returns the string that uniquely identifies bo the WebHandlerFactory and resulting WebHandler's that will be attached +// Binding returns the string that uniquely identifies bo the WebHandlerFactory and resulting WebHandler's that will be attached // to some WebListener and its resulting Server. func (api *API) Binding() string { return api.binding } -// Returns the options associated with thsi API binding. +// Options returns the options associated with thsi API binding. func (api *API) Options() map[interface{}]interface{} { return api.options } -// Parses the configuration map for an API. +// Parse the configuration map for an API. func (api *API) Parse(apiConfigMap map[interface{}]interface{}) error { if bindingInterface, ok := apiConfigMap["binding"]; ok { if binding, ok := bindingInterface.(string); ok { @@ -327,7 +328,7 @@ func (api *API) Parse(apiConfigMap map[interface{}]interface{}) error { return nil } -// Validates this configuration object. +// Validate this configuration object. func (api *API) Validate() error { if api.Binding() == "" { return errors.New("binding must be specified") @@ -336,14 +337,14 @@ func (api *API) Validate() error { return nil } -// Represents the interface:port address of where a http.Server should listen for a WebListener and the public +// BindPoint represents the interface:port address of where a http.Server should listen for a WebListener and the public // address that should be used to address it. type BindPoint struct { InterfaceAddress string // : Address string //: } -// Parses the configuration map for a BindPoint. +// Parse the configuration map for a BindPoint. func (bindPoint *BindPoint) Parse(config map[interface{}]interface{}) error { if interfaceVal, ok := config["interface"]; ok { if address, ok := interfaceVal.(string); ok { @@ -364,7 +365,7 @@ func (bindPoint *BindPoint) Parse(config map[interface{}]interface{}) error { return nil } -// Validates this configuration object. +// Validate this configuration object. func (bindPoint *BindPoint) Validate() error { if bindPoint.InterfaceAddress == "" { return errors.New("value for address must be provided") @@ -377,19 +378,19 @@ func (bindPoint *BindPoint) Validate() error { return nil } -// The WebListener shared options configuration struct. +// Options is the shared options for a WebListener. type Options struct { TimeoutOptions TlsVersionOptions } -// Defaults all necessary values +// Default provides defaults for all necessary values func (options *Options) Default() { options.TimeoutOptions.Default() options.TlsVersionOptions.Default() } -// Parses a configuariont map +// Parse parses a configuration map func (options *Options) Parse(optionsMap map[interface{}]interface{}) error { if err := options.TimeoutOptions.Parse(optionsMap); err != nil { return fmt.Errorf("error parsing options: %v", err) @@ -402,21 +403,21 @@ func (options *Options) Parse(optionsMap map[interface{}]interface{}) error { return nil } -//Represents http timeout options +// TimeoutOptions represents http timeout options type TimeoutOptions struct { ReadTimeout time.Duration IdleTimeout time.Duration WriteTimeout time.Duration } -// Defaults all http. timeout options +// Default defaults all HTTP timeout options func (timeoutOptions *TimeoutOptions) Default() { timeoutOptions.WriteTimeout = time.Second * 10 timeoutOptions.ReadTimeout = time.Second * 5 timeoutOptions.IdleTimeout = time.Second * 5 } -// Parses a config map +// Parse parses a config map func (timeoutOptions *TimeoutOptions) Parse(config map[interface{}]interface{}) error { if interfaceVal, ok := config["readTimeoutMs"]; ok { if readTimeoutMs, ok := interfaceVal.(int); ok { @@ -445,7 +446,7 @@ func (timeoutOptions *TimeoutOptions) Parse(config map[interface{}]interface{}) return nil } -// Validtes all settings +// Validate validates all settings and return nil or an error func (timeoutOptions *TimeoutOptions) Validate() error { if timeoutOptions.WriteTimeout <= 0 { return fmt.Errorf("value [%s] for writeTimeout too low, must be positive", timeoutOptions.WriteTimeout.String()) @@ -462,7 +463,7 @@ func (timeoutOptions *TimeoutOptions) Validate() error { return nil } -// Represents TLS version options +// TlsVersionOptions represents TLS version options type TlsVersionOptions struct { MinTLSVersion int minTLSVersionStr string @@ -471,7 +472,7 @@ type TlsVersionOptions struct { maxTLSVersionStr string } -// A map of configuration strings to TLS version identifiers +// tlsVersionMap is a map of configuration strings to TLS version identifiers var tlsVersionMap = map[string]int{ "TLS1.0": tls.VersionTLS10, "TLS1.1": tls.VersionTLS11, @@ -479,13 +480,13 @@ var tlsVersionMap = map[string]int{ "TLS1.3": tls.VersionTLS13, } -// Defaults TLS versions +// Default defaults TLS versions func (tlsVersionOptions *TlsVersionOptions) Default() { tlsVersionOptions.MinTLSVersion = tls.VersionTLS12 tlsVersionOptions.MaxTLSVersion = tls.VersionTLS13 } -// Parses a config map +// Parse parses a config map func (tlsVersionOptions *TlsVersionOptions) Parse(config map[interface{}]interface{}) error { if interfaceVal, ok := config["minTLSVersion"]; ok { var ok bool @@ -516,7 +517,7 @@ func (tlsVersionOptions *TlsVersionOptions) Parse(config map[interface{}]interfa return nil } -// Validates the configuration values +// Validate validates the configuration values and returns nil or error func (tlsVersionOptions *TlsVersionOptions) Validate() error { if tlsVersionOptions.MinTLSVersion > tlsVersionOptions.MaxTLSVersion { return fmt.Errorf("minTLSVersion [%s] must be less than or equal to maxTLSVersion [%s]", tlsVersionOptions.minTLSVersionStr, tlsVersionOptions.maxTLSVersionStr) diff --git a/controller/xweb/contextutil.go b/controller/xweb/contextutil.go index d1fe43133..1a15c717f 100644 --- a/controller/xweb/contextutil.go +++ b/controller/xweb/contextutil.go @@ -18,8 +18,8 @@ package xweb import "context" -// Utility function to retrieve a WebHandler reference, that the demux http.Handler deferred to, during downstream -// http.Handler processing from the http.Request context. +// WebHandlerFromContext us a utility function to retrieve a WebHandler reference, that the demux http.Handler +// deferred to, during downstream http.Handler processing from the http.Request context. func WebHandlerFromContext(ctx context.Context) *WebHandler { if val := ctx.Value(WebHandlerContextKey); val != nil { if handler, ok := val.(*WebHandler); ok { @@ -29,8 +29,8 @@ func WebHandlerFromContext(ctx context.Context) *WebHandler { return nil } -// Utility function to retrieve a BindPoint reference from the http.Request context that indicates what interface and -//port combo the incoming http.Request was handled on. +// ListenAddressFromContext is a utility function to retrieve a BindPoint reference from the http.Request context +// that indicates what interface and port combo the incoming http.Request was handled on. func ListenAddressFromContext(ctx context.Context) *BindPoint { if val := ctx.Value(BindPointContextKey); val != nil { if handler, ok := val.(*BindPoint); ok { diff --git a/controller/xweb/demux.go b/controller/xweb/demux.go index 53f2db197..2ed3beaf9 100644 --- a/controller/xweb/demux.go +++ b/controller/xweb/demux.go @@ -23,21 +23,21 @@ import ( "strings" ) -// Generates a http.Handler that interrogates a http.Request and routes them to WebHandlers. The selected WebHandler -// is added to the context with a key of WebHandlerContextKey. Each DemuxFactory implementation must define +// DemuxFactory generates a http.Handler that interrogates a http.Request and routes them to WebHandlers. The selected +// WebHandler is added to the context with a key of WebHandlerContextKey. Each DemuxFactory implementation must define // its own behaviors for an unmatched http.Request. type DemuxFactory interface { Build(handlers []WebHandler) (http.Handler, error) } -// A DemuxFactory that routes http.Request requests to a specific WebHandler from a set of WebHandler's by URL path prefixes. -// a http.Handler for NoHandlerFound can be provided to specify behavior to perform when a WebHandler is not selected. By default -// an empty response with a http.StatusNotFound (404) will be sent. +// PathPrefixDemuxFactory is a DemuxFactory that routes http.Request requests to a specific WebHandler from a set of +// WebHandler's by URL path prefixes. A http.Handler for NoHandlerFound can be provided to specify behavior to perform +// when a WebHandler is not selected. By default an empty response with a http.StatusNotFound (404) will be sent. type PathPrefixDemuxFactory struct { NoHandlerFound http.Handler } -// Performs WebHandler selection based on URL path prefixes +// Build performs WebHandler selection based on URL path prefixes func (factory *PathPrefixDemuxFactory) Build(handlers []WebHandler) (http.Handler, error) { handlerMap := map[string]WebHandler{} @@ -64,10 +64,43 @@ func (factory *PathPrefixDemuxFactory) Build(handlers []WebHandler) (http.Handle }), nil } -// Provide an empty 404 for unmached path if NoHandlerFound is nil, otherwise call and defer to NoHandlerFound. +// noHandlerFound provides an empty 404 for unmatched paths if NoHandlerFound is nil, otherwise call and defer to NoHandlerFound. func (factory *PathPrefixDemuxFactory) noHandlerFound(writer http.ResponseWriter, request *http.Request) { if factory.NoHandlerFound != nil { - //defer to externally specified http.Handler fun + //defer to externally specified http.Handler func + factory.NoHandlerFound.ServeHTTP(writer, request) + return + } + + writer.WriteHeader(http.StatusNotFound) + _, _ = writer.Write([]byte{}) +} + +// IsHandledDemuxFactory is a DemuxFactory that routes http.Request requests to a specific WebHandler by delegating +// to the WebHandler's IsHandled function. +type IsHandledDemuxFactory struct { + NoHandlerFound http.Handler +} + +// Build performs WebHandler selection based on IsHandled() +func (factory *IsHandledDemuxFactory) Build(handlers []WebHandler) (http.Handler, error) { + return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + for _, handler := range handlers { + if handler.IsHandler(request) { + ctx := context.WithValue(request.Context(), WebHandlerContextKey, handler) + newRequest := request.WithContext(ctx) + handler.ServeHTTP(writer, newRequest) + return + } + } + factory.noHandlerFound(writer, request) + }), nil +} + +// noHandlerFound provides an empty 404 for unmatched paths if NoHandlerFound is nil, otherwise call and defer to NoHandlerFound. +func (factory *IsHandledDemuxFactory) noHandlerFound(writer http.ResponseWriter, request *http.Request) { + if factory.NoHandlerFound != nil { + //defer to externally specified http.Handler func factory.NoHandlerFound.ServeHTTP(writer, request) return } diff --git a/controller/xweb/registry.go b/controller/xweb/registry.go index 90394c738..d229258fb 100644 --- a/controller/xweb/registry.go +++ b/controller/xweb/registry.go @@ -21,25 +21,25 @@ import ( "net/http" ) -// Describes a registry of binding to WebHandlerFactory registrations +// WebHandlerFactoryRegistry describes a registry of binding to WebHandlerFactory registrations type WebHandlerFactoryRegistry interface { Add(factory WebHandlerFactory) error Get(binding string) WebHandlerFactory } -// A basic WebHandlerFactoryRegistry implementation backed by a simple mapping of binding to WebHandlerFactories +// WebHandlerFactoryRegistryImpl is a basic WebHandlerFactoryRegistry implementation backed by a simple mapping of binding (string) to WebHandlerFactories type WebHandlerFactoryRegistryImpl struct { factories map[string]WebHandlerFactory } -// Create a new WebHandlerFactoryRegistryImpl +// NewWebHandlerFactoryRegistryImpl creates a new WebHandlerFactoryRegistryImpl func NewWebHandlerFactoryRegistryImpl() *WebHandlerFactoryRegistryImpl { return &WebHandlerFactoryRegistryImpl{ factories: map[string]WebHandlerFactory{}, } } -// Adds a factory to the registry. Errors if a previous factory with the same binding is registered. +// Add adds a factory to the registry. Errors if a previous factory with the same binding is registered. func (registry WebHandlerFactoryRegistryImpl) Add(factory WebHandlerFactory) error { if _, ok := registry.factories[factory.Binding()]; ok { return fmt.Errorf("binding [%s] already registered", factory.Binding()) @@ -50,32 +50,33 @@ func (registry WebHandlerFactoryRegistryImpl) Add(factory WebHandlerFactory) err return nil } -// Retrieves a factory based on a binding or nil if no factory for the binding is registered +// Get retrieves a factory based on a binding or nil if no factory for the binding is registered func (registry WebHandlerFactoryRegistryImpl) Get(binding string) WebHandlerFactory { return registry.factories[binding] } -// An interface defines the minimum operations necessary to convert configuration into a WebHandler by some WebHandlerFactory -// The APIBinding.Binding() value is used to map configuration data to specific WebHandlerFactory instances that -// generate a WebHandler with the same binding value. +// APIBinding is an interface defines the minimum operations necessary to convert configuration into a WebHandler +// by some WebHandlerFactory. The APIBinding.Binding() value is used to map configuration data to specific +// WebHandlerFactory instances that generate a WebHandler with the same binding value. type APIBinding interface { Binding() string Options() map[interface{}]interface{} } -// A http.Handler with options, binding, and information for a specific web API that was generated from -// a WebHandlerFactory. +// WebHandler is an interface that is a http.Handler with options, binding, and information for a specific web API +// that was generated from a WebHandlerFactory. type WebHandler interface { Binding() string Options() map[interface{}]interface{} RootPath() string + IsHandler(r *http.Request) bool http.Handler } -// Generates WebHandler instances. Factories can use a single instance or multiple instances based on need. -// This interface allows WebHandler logic to be reused across multiple xweb.Server's while delegating the instance -// management to the factory. +// The WebHandlerFactory interface generates WebHandler instances. Factories can use a single instance or multiple +// instances based on need. This interface allows WebHandler logic to be reused across multiple xweb.Server's while +// delegating the instance management to the factory. type WebHandlerFactory interface { Binding() string New(webListener *WebListener, options map[interface{}]interface{}) (WebHandler, error) diff --git a/controller/xweb/server.go b/controller/xweb/server.go index 9fb9479e5..bcd7bc8ef 100644 --- a/controller/xweb/server.go +++ b/controller/xweb/server.go @@ -35,9 +35,15 @@ const ( BindPointContextKey = ContextKey("XWebBindPointContextKey") ) -// Represents all of the http.Server's and http.Handler's necessary to run a single xweb.WebListener +type namedHttpServer struct { + *http.Server + ApiBindingList []string + WebListenerName string +} + +// Server represents all of the http.Server's and http.Handler's necessary to run a single xweb.WebListener type Server struct { - httpServers []*http.Server + httpServers []*namedHttpServer corsOptions []handlers.CORSOption logWriter *io.PipeWriter options *Options @@ -46,7 +52,7 @@ type Server struct { OnHandlerPanic func(writer http.ResponseWriter, request *http.Request, panicVal interface{}) } -// Create a new xweb.Server from an xweb.WebListener. All necessary http.Handler's will be created from the supplied +// NewServer creates a new xweb.Server from an xweb.WebListener. All necessary http.Handler's will be created from the supplied // DemuxFactory and WebHandlerFactoryRegistry. func NewServer(webListener *WebListener, demuxFactory DemuxFactory, handlerFactoryRegistry WebHandlerFactoryRegistry) (*Server, error) { logWriter := pfxlog.Logger().Writer() @@ -60,10 +66,11 @@ func NewServer(webListener *WebListener, demuxFactory DemuxFactory, handlerFacto server := &Server{ logWriter: logWriter, config: &webListener, - httpServers: []*http.Server{}, + httpServers: []*namedHttpServer{}, } var webHandlers []WebHandler + var apiBindingList []string for _, api := range webListener.APIs { if factory := handlerFactoryRegistry.Get(api.Binding()); factory != nil { @@ -71,6 +78,7 @@ func NewServer(webListener *WebListener, demuxFactory DemuxFactory, handlerFacto pfxlog.Logger().Fatalf("encountered error building handler for api binding [%s]: %v", api.Binding(), err) } else { webHandlers = append(webHandlers, webHandler) + apiBindingList = append(apiBindingList, api.binding) } } else { pfxlog.Logger().Fatalf("encountered api binding [%s] which has no associated factory registered", api.Binding()) @@ -84,16 +92,20 @@ func NewServer(webListener *WebListener, demuxFactory DemuxFactory, handlerFacto } for _, bindPoint := range webListener.BindPoints { - httpServer := &http.Server{ - Addr: bindPoint.InterfaceAddress, - WriteTimeout: webListener.Options.WriteTimeout, - ReadTimeout: webListener.Options.ReadTimeout, - IdleTimeout: webListener.Options.WriteTimeout, - Handler: server.wrap(demuxWebHandler, bindPoint), - TLSConfig: tlsConfig, - ErrorLog: log.New(logWriter, "", 0), + namedServer := &namedHttpServer{ + ApiBindingList: apiBindingList, + WebListenerName: webListener.Name, + Server: &http.Server{ + Addr: bindPoint.InterfaceAddress, + WriteTimeout: webListener.Options.WriteTimeout, + ReadTimeout: webListener.Options.ReadTimeout, + IdleTimeout: webListener.Options.WriteTimeout, + Handler: server.wrap(demuxWebHandler, bindPoint), + TLSConfig: tlsConfig, + ErrorLog: log.New(logWriter, "", 0), + }, } - server.httpServers = append(server.httpServers, httpServer) + server.httpServers = append(server.httpServers, namedServer) } return server, nil @@ -134,7 +146,7 @@ func (server *Server) Start() error { logger := pfxlog.Logger() for _, httpServer := range server.httpServers { - logger.Info("starting API to listen and serve tls on: ", httpServer.Addr) + logger.Infof("starting API to listen and serve tls on %s for web listener %s with APIs: %v", httpServer.Addr, httpServer.WebListenerName, httpServer.ApiBindingList) err := httpServer.ListenAndServeTLS("", "") if err != http.ErrServerClosed { @@ -145,7 +157,7 @@ func (server *Server) Start() error { return nil } -// Stop the server and all underlying http.Server's +// Shutdown stops the server and all underlying http.Server's func (server *Server) Shutdown(ctx context.Context) { _ = server.logWriter.Close() diff --git a/controller/xweb/web.go b/controller/xweb/web.go index cc726c54f..d16e869e9 100644 --- a/controller/xweb/web.go +++ b/controller/xweb/web.go @@ -20,17 +20,16 @@ Package xweb provides facilities to creating composable xweb.WebHandlers and htt Basics xweb provides customizable and extendable components to stand up multiple http.Server's listening on one or more -network interfaces. +network interfaces and ports. Each xweb.Xweb is responsible for defining configuration sections to be parsed, parsing the configuration, starting servers, and shutting down relevant server. An example implementation is included in the package: xweb.XwebImpl. This implementation should cover most use cases. In addition xweb.XwebImpl makes use of xweb.Config which is reusable -component for parsing xweb.XwebImpl configuration sections. Both xweb.Xweb xweb.Config assume that configuration will -be acquired from some source and be presented as a map of interface{}-to-interface{} values -(map[interface{}]interface{}) per the openziti/foundation config.Subconfig pattern. +component for parsing xweb.XwebImpl configuration sections. Both xweb.Xweb and xweb.Config assume that configuration +will be acquired from some source and be presented as a map of interface{}-to-interface{} values. xweb.Config configuration sections allow the definition of an array of xweb.WebListener. In turn each xweb.WebListener -can listen on many interface/port combinations specified by an array of xweb.BindPoint and host many http.Handler's +can listen on many interface/port combinations specified by an array of xweb.BindPoint's and host many http.Handler's by defining an array of xweb.API's that are converted into xweb.WebHandler's. xweb.WebHandler's are http.Handler's with meta data and can be as complex or as simple as necessary - using other libraries or only the standard http Go capabilities. @@ -49,7 +48,7 @@ import ( "time" ) -// Implements config.Subconfig to allow Xweb implementations to be used during the normal Ziti component startup +// Xweb implements config.Subconfig to allow Xweb implementations to be used during the normal Ziti component startup // and configuration phase. type Xweb interface { Enabled() bool @@ -63,7 +62,7 @@ const ( WebSection = "web" ) -// A simple implementation of xweb.XWeb used for registration and configuration from controller.Controller. +// XwebImpl is a simple implementation of xweb.XWeb, used for registration and configuration from controller.Controller. // Implements necessary interfaces to be a config.Subconfig. type XwebImpl struct { Config *Config @@ -75,7 +74,7 @@ type XwebImpl struct { func NewXwebImpl(registry WebHandlerFactoryRegistry) *XwebImpl { return &XwebImpl{ Registry: registry, - DemuxFactory: &PathPrefixDemuxFactory{}, + DemuxFactory: &IsHandledDemuxFactory{}, Config: &Config{ DefaultIdentitySection: DefaultIdentitySection, WebSection: WebSection, @@ -83,12 +82,12 @@ func NewXwebImpl(registry WebHandlerFactoryRegistry) *XwebImpl { } } -// Whether this subconfig should be considered enabled +// Enabled returns true/false on whether this subconfig should be considered enabled func (xwebimpl *XwebImpl) Enabled() bool { return xwebimpl.Config.Enabled() } -// Handle subconfig operations for xweb.Xweb components +// LoadConfig handles subconfig operations for xweb.Xweb components func (xwebimpl *XwebImpl) LoadConfig(cfgmap map[interface{}]interface{}) error { if err := xwebimpl.Config.Parse(cfgmap); err != nil { return err @@ -102,7 +101,7 @@ func (xwebimpl *XwebImpl) LoadConfig(cfgmap map[interface{}]interface{}) error { return nil } -// Starts the necessary xweb.Server's +// Run starts the necessary xweb.Server's func (xwebimpl *XwebImpl) Run() { for _, webListener := range xwebimpl.Config.WebListeners { server, err := NewServer(webListener, xwebimpl.DemuxFactory, xwebimpl.Registry) @@ -113,13 +112,15 @@ func (xwebimpl *XwebImpl) Run() { xwebimpl.servers = append(xwebimpl.servers, server) - if err := server.Start(); err != nil { - pfxlog.Logger().Errorf("error starting xgweb_rest server %s: %v", webListener.Name, err) - } + go func(){ + if err := server.Start(); err != nil { + pfxlog.Logger().Errorf("error starting xweb_rest server %s: %v", webListener.Name, err) + } + }() } } -// Stop all running xweb.Server's +// Shutdown stop all running xweb.Server's func (xwebimpl *XwebImpl) Shutdown() { for _, server := range xwebimpl.servers { localServer := server @@ -128,6 +129,5 @@ func (xwebimpl *XwebImpl) Shutdown() { defer cancel() localServer.Shutdown(ctx) }() - } }