mirror of
https://github.com/openziti/ziti.git
synced 2026-10-12 23:32:02 +00:00
Merge pull request openziti/fabric#235 from openziti/xweb.comments.fix.multi.server.startup
fixes xweb comments, fixes xweb startup
This commit is contained in:
+30
-29
@@ -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 // <interface>:<port>
|
||||
Address string //<ip/host>:<port>
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+14
-13
@@ -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)
|
||||
|
||||
+27
-15
@@ -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()
|
||||
|
||||
|
||||
+16
-16
@@ -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)
|
||||
}()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user