package server import ( "context" "crypto/tls" "sync" "time" "go-micro.dev/v5/broker" "go-micro.dev/v5/codec" "go-micro.dev/v5/debug/trace" "go-micro.dev/v5/logger" "go-micro.dev/v5/registry" "go-micro.dev/v5/transport" ) type RouterOptions struct { Logger logger.Logger } type RouterOption func(o *RouterOptions) func NewRouterOptions(opt ...RouterOption) RouterOptions { opts := RouterOptions{ Logger: logger.DefaultLogger, } for _, o := range opt { o(&opts) } return opts } // WithRouterLogger sets the underline router logger. func WithRouterLogger(l logger.Logger) RouterOption { return func(o *RouterOptions) { o.Logger = l } } type Options struct { Logger logger.Logger Broker broker.Broker Registry registry.Registry Tracer trace.Tracer Transport transport.Transport // Other options for implementations of the interface // can be stored in a context Context context.Context // The router for requests Router Router // RegisterCheck runs a check function before registering the service RegisterCheck func(context.Context) error Metadata map[string]string // TLSConfig specifies tls.Config for secure serving TLSConfig *tls.Config Codecs map[string]codec.NewCodec Name string Id string Version string Advertise string Address string HdlrWrappers []HandlerWrapper ListenOptions []transport.ListenOption SubWrappers []SubscriberWrapper // The interval on which to register RegisterInterval time.Duration // The register expiry time RegisterTTL time.Duration } // NewOptions creates new server options. func NewOptions(opt ...Option) Options { opts := Options{ Codecs: make(map[string]codec.NewCodec), Metadata: map[string]string{}, RegisterInterval: DefaultRegisterInterval, RegisterTTL: DefaultRegisterTTL, Logger: logger.DefaultLogger, } for _, o := range opt { o(&opts) } if opts.Broker == nil { opts.Broker = broker.DefaultBroker } if opts.Registry == nil { opts.Registry = registry.DefaultRegistry } if opts.Transport == nil { opts.Transport = transport.DefaultTransport } if opts.RegisterCheck == nil { opts.RegisterCheck = DefaultRegisterCheck } if len(opts.Address) == 0 { opts.Address = DefaultAddress } if len(opts.Name) == 0 { opts.Name = DefaultName } if len(opts.Id) == 0 { opts.Id = DefaultId } if len(opts.Version) == 0 { opts.Version = DefaultVersion } return opts } // Server name. func Name(n string) Option { return func(o *Options) { o.Name = n } } // Unique server id. func Id(id string) Option { return func(o *Options) { o.Id = id } } // Version of the service. func Version(v string) Option { return func(o *Options) { o.Version = v } } // Address to bind to - host:port. func Address(a string) Option { return func(o *Options) { o.Address = a } } // The address to advertise for discovery - host:port. func Advertise(a string) Option { return func(o *Options) { o.Advertise = a } } // Broker to use for pub/sub. func Broker(b broker.Broker) Option { return func(o *Options) { o.Broker = b } } // Codec to use to encode/decode requests for a given content type. func Codec(contentType string, c codec.NewCodec) Option { return func(o *Options) { o.Codecs[contentType] = c } } // Context specifies a context for the service. // Can be used to signal shutdown of the service // Can be used for extra option values. func Context(ctx context.Context) Option { return func(o *Options) { o.Context = ctx } } // Registry used for discovery. func Registry(r registry.Registry) Option { return func(o *Options) { o.Registry = r } } // Tracer mechanism for distributed tracking. func Tracer(t trace.Tracer) Option { return func(o *Options) { o.Tracer = t } } // Transport mechanism for communication e.g http, rabbitmq, etc. func Transport(t transport.Transport) Option { return func(o *Options) { o.Transport = t } } // Metadata associated with the server. func Metadata(md map[string]string) Option { return func(o *Options) { o.Metadata = md } } // RegisterCheck run func before registry service. func RegisterCheck(fn func(context.Context) error) Option { return func(o *Options) { o.RegisterCheck = fn } } // Register the service with a TTL. func RegisterTTL(t time.Duration) Option { return func(o *Options) { o.RegisterTTL = t } } // Register the service with at interval. func RegisterInterval(t time.Duration) Option { return func(o *Options) { o.RegisterInterval = t } } // TLSConfig specifies a *tls.Config. func TLSConfig(t *tls.Config) Option { return func(o *Options) { // set the internal tls o.TLSConfig = t // set the default transport if one is not // already set. Required for Init call below. if o.Transport == nil { o.Transport = transport.DefaultTransport } // set the transport tls o.Transport.Init( transport.Secure(true), transport.TLSConfig(t), ) } } // WithRouter sets the request router. func WithRouter(r Router) Option { return func(o *Options) { o.Router = r } } // WithLogger sets the underline logger. func WithLogger(l logger.Logger) Option { return func(o *Options) { o.Logger = l } } // Wait tells the server to wait for requests to finish before exiting // If `wg` is nil, server only wait for completion of rpc handler. // For user need finer grained control, pass a concrete `wg` here, server will // wait against it on stop. func Wait(wg *sync.WaitGroup) Option { return func(o *Options) { if o.Context == nil { o.Context = context.Background() } if wg == nil { wg = new(sync.WaitGroup) } o.Context = context.WithValue(o.Context, wgKey{}, wg) } } // Adds a handler Wrapper to a list of options passed into the server. func WrapHandler(w HandlerWrapper) Option { return func(o *Options) { o.HdlrWrappers = append(o.HdlrWrappers, w) } } // Adds a subscriber Wrapper to a list of options passed into the server. func WrapSubscriber(w SubscriberWrapper) Option { return func(o *Options) { o.SubWrappers = append(o.SubWrappers, w) } } // Add transport.ListenOption to the ListenOptions list, when using it, it will be passed to the // httpTransport.Listen() method. func ListenOption(option transport.ListenOption) Option { return func(o *Options) { o.ListenOptions = append(o.ListenOptions, option) } }