mirror of
https://github.com/nabbar/golib.git
synced 2025-09-26 20:01:15 +08:00
Package HTTP Client:
- Add DNS Mapper to force destination for a fqdn source - Allow wildcard and multi wildcard for fqdn source - DNS Mapper create Transport, Dialer & http client - DNS Mapper allow a config input to customize timeout, limit and TLS config - DNS Mapper use a gloabl transport connection poller - DNS Mapper implement DialContext & Dial method for transport - DNS Mapper use cache to accelerate process - DNS Mapper cache is only dnsmapper, not DNS cache - Replace old helper for http client with DNSMapper - Add default DNSMapper into the main lib of http client - Allow to overide the default DNS Mapper with a new one - Add ticker to force clean idle connection every given duration - "Compatible" with old config, as the default config will be used instead of old client build - Clean code and fix minor bugs - Add config component to allow use a global config - Config Component httpcli can overide default httpcli dns mapper when updated Package Certificates - Add function type to impose function that return a slice of rootCA string - update config/component/tls by replacing mutex with atomic - optimize some code Package Config - expand errors code index to add component httpcli Package Config/component: - database: add new validation, that config key existing into viper - head: add new validation, that config key existing into viper - http: add new validation, that config key existing into viper - ldap: add new validation, that config key existing into viper - log: add new validation, that config key existing into viper - mail: add new validation, that config key existing into viper - smtp: add new validation, that config key existing into viper Package AWS: - update package following update of httpcli - use interface for http cli that implement the Do function - update following the config/component/aws - rework config/component/aws to use atomic instead of mutex - update test unit following change Package Request: - update following http client update - use interface of HTTP Client that implement DO function, instead of http client struct pointer - update config & code following - apply same modification into config/component/request - update config/component/request by replacing mutex to atomic Package Server - add function Uptime to model to expose the duration since last start Package Semaphore - apply change name of constant following bump of lib associated Package Crypt - fix bug into reader to remove suffix of EOF if prevent Package Errors: - expand index module to add DNS Mapper client Package HTTP Server: - update monitor to apply changes Package Socket: - add additional check if reading error: if buffer has data, send it to handler before break run Other: - bump dependencies
This commit is contained in:
@@ -92,8 +92,7 @@ var _ = BeforeSuite(func() {
|
||||
secretKey = libpwd.Generate(64)
|
||||
)
|
||||
|
||||
htp, err = libhtc.GetClient(libhtc.GetTransport(false, false, false), true, libhtc.ClientTimeout30Sec)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
htp = libhtc.GetClient()
|
||||
Expect(htp).NotTo(BeNil())
|
||||
|
||||
cfg = awscfg.NewConfig("", accessKey, secretKey, uri, "us-east-1")
|
||||
@@ -119,7 +118,8 @@ var _ = BeforeSuite(func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(cli).NotTo(BeNil())
|
||||
|
||||
cli.ForcePathStyle(ctx, true)
|
||||
err = cli.ForcePathStyle(ctx, true)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
name, err = lbuuid.GenerateUUID()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@@ -45,9 +45,8 @@ type Model struct {
|
||||
}
|
||||
|
||||
type ModelStatus struct {
|
||||
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required"`
|
||||
HTTPClient libhtc.Options `json:"http-client" yaml:"http-client" toml:"http-client" mapstructure:"http-client" validate:""`
|
||||
Monitor libreq.OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required"`
|
||||
Monitor libreq.OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
}
|
||||
|
||||
type awsModel struct {
|
||||
|
@@ -47,9 +47,8 @@ type Model struct {
|
||||
}
|
||||
|
||||
type ModelStatus struct {
|
||||
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required"`
|
||||
HTTPClient libhtc.Options `json:"http-client" yaml:"http-client" toml:"http-client" mapstructure:"http-client" validate:""`
|
||||
Monitor libreq.OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required"`
|
||||
Monitor libreq.OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
}
|
||||
|
||||
type awsModel struct {
|
||||
|
@@ -36,6 +36,7 @@ import (
|
||||
|
||||
type FctHttpClient func(def TLSConfig, servername string) *http.Client
|
||||
type FctTLSDefault func() TLSConfig
|
||||
type FctRootCA func() []string
|
||||
|
||||
type TLSConfig interface {
|
||||
AddRootCAString(rootCA string) bool
|
||||
|
@@ -27,12 +27,8 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
libaws "github.com/nabbar/golib/aws"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
@@ -40,9 +36,6 @@ import (
|
||||
)
|
||||
|
||||
func (o *componentAws) _getKey() string {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyCptKey); !l {
|
||||
return ""
|
||||
} else if i == nil {
|
||||
@@ -54,32 +47,7 @@ func (o *componentAws) _getKey() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) _getTLS() libtls.TLSConfig {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.t == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return o.t()
|
||||
}
|
||||
|
||||
func (o *componentAws) _getHttpClient() *http.Client {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.c == nil {
|
||||
return &http.Client{}
|
||||
}
|
||||
|
||||
return o.c()
|
||||
}
|
||||
|
||||
func (o *componentAws) _getFctVpr() libvpr.FuncViper {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyFctViper); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -112,9 +80,6 @@ func (o *componentAws) _getSPFViper() *spfvbr.Viper {
|
||||
}
|
||||
|
||||
func (o *componentAws) _getFctCpt() cfgtps.FuncCptGet {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyFctGetCpt); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -127,9 +92,6 @@ func (o *componentAws) _getFctCpt() cfgtps.FuncCptGet {
|
||||
}
|
||||
|
||||
func (o *componentAws) _getVersion() libver.Version {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyCptVersion); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -150,9 +112,6 @@ func (o *componentAws) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
|
||||
}
|
||||
|
||||
func (o *componentAws) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(key); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -178,7 +137,6 @@ func (o *componentAws) _runCli() error {
|
||||
cli libaws.AWS
|
||||
cfg libaws.Config
|
||||
mon *libreq.OptionsHealth
|
||||
htc *libhtc.Options
|
||||
opt *libreq.Options
|
||||
req libreq.Request
|
||||
prt = ErrorComponentReload
|
||||
@@ -188,51 +146,33 @@ func (o *componentAws) _runCli() error {
|
||||
prt = ErrorComponentStart
|
||||
}
|
||||
|
||||
if cfg, mon, htc, err = o._getConfig(); err != nil {
|
||||
if cfg, mon, err = o._getConfig(); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
if htc != nil {
|
||||
var h = *htc
|
||||
o.RegisterHTTPClient(func() *http.Client {
|
||||
if cl, er := h.GetClient(o._getTLS(), ""); er == nil {
|
||||
return cl
|
||||
}
|
||||
|
||||
return &http.Client{}
|
||||
})
|
||||
}
|
||||
|
||||
if cli, err = libaws.New(o.x.GetContext(), cfg, o._getHttpClient()); err != nil {
|
||||
if cli, err = libaws.New(o.x.GetContext(), cfg, o.getClient()); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
if mon != nil && mon.Enable {
|
||||
opt = &libreq.Options{
|
||||
Endpoint: "",
|
||||
HttpClient: *htc,
|
||||
Auth: libreq.OptionsAuth{},
|
||||
Health: *mon,
|
||||
Endpoint: "",
|
||||
Auth: libreq.OptionsAuth{},
|
||||
Health: *mon,
|
||||
}
|
||||
|
||||
opt.SetDefaultTLS(o._getTLS)
|
||||
opt.SetDefaultLog(o.getLogger)
|
||||
|
||||
o.m.Lock()
|
||||
req = o.r
|
||||
o.m.Unlock()
|
||||
|
||||
if req != nil {
|
||||
if req = o.getRequest(); req != nil {
|
||||
if req, err = opt.Update(o.x.GetContext, req); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
} else if req, err = opt.New(o.x.GetContext); err != nil {
|
||||
req.RegisterHTTPClient(o.getClient())
|
||||
} else if req, err = opt.New(o.x.GetContext, o.getClient()); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
o.m.Lock()
|
||||
o.r = req
|
||||
o.m.Unlock()
|
||||
o.setRequest(req)
|
||||
}
|
||||
|
||||
if mon != nil {
|
||||
@@ -241,9 +181,7 @@ func (o *componentAws) _runCli() error {
|
||||
}
|
||||
}
|
||||
|
||||
o.m.Lock()
|
||||
o.a = cli
|
||||
o.m.Unlock()
|
||||
o.SetAws(cli)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -55,17 +55,6 @@ func (o *componentAws) Type() string {
|
||||
}
|
||||
|
||||
func (o *componentAws) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
if o.x == nil {
|
||||
o.x = libctx.NewConfig[uint8](ctx)
|
||||
} else {
|
||||
x := libctx.NewConfig[uint8](ctx)
|
||||
x.Merge(o.x)
|
||||
o.x = x
|
||||
}
|
||||
|
||||
o.x.Store(keyCptKey, key)
|
||||
o.x.Store(keyFctGetCpt, get)
|
||||
o.x.Store(keyFctViper, vpr)
|
||||
@@ -84,10 +73,11 @@ func (o *componentAws) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
|
||||
}
|
||||
|
||||
func (o *componentAws) IsStarted() bool {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
if o.s.Load() {
|
||||
return o.getAws() != nil
|
||||
}
|
||||
|
||||
return o.a != nil
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *componentAws) IsRunning() bool {
|
||||
@@ -95,6 +85,7 @@ func (o *componentAws) IsRunning() bool {
|
||||
}
|
||||
|
||||
func (o *componentAws) Start() error {
|
||||
o.s.Store(true)
|
||||
return o._run()
|
||||
}
|
||||
|
||||
@@ -103,17 +94,11 @@ func (o *componentAws) Reload() error {
|
||||
}
|
||||
|
||||
func (o *componentAws) Stop() {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.a = nil
|
||||
o.s.Store(false)
|
||||
return
|
||||
}
|
||||
|
||||
func (o *componentAws) Dependencies() []string {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
var def = make([]string, 0)
|
||||
|
||||
if o == nil {
|
||||
@@ -132,9 +117,6 @@ func (o *componentAws) Dependencies() []string {
|
||||
}
|
||||
|
||||
func (o *componentAws) SetDependencies(d []string) error {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.x == nil {
|
||||
return ErrorComponentNotInitialized.Error(nil)
|
||||
} else {
|
||||
|
@@ -27,10 +27,11 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libaws "github.com/nabbar/golib/aws"
|
||||
cfgstd "github.com/nabbar/golib/aws/configAws"
|
||||
cfgcus "github.com/nabbar/golib/aws/configCustom"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -111,102 +112,93 @@ func (o *componentAws) RegisterFlag(Command *spfcbr.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentAws) _getConfig() (libaws.Config, *libreq.OptionsHealth, *libhtc.Options, error) {
|
||||
func (o *componentAws) _getConfig() (libaws.Config, *libreq.OptionsHealth, error) {
|
||||
var (
|
||||
key string
|
||||
cfg libaws.Config
|
||||
flg = o._getFlagUpdate()
|
||||
mon *libreq.OptionsHealth
|
||||
htc *libhtc.Options
|
||||
vpr libvpr.Viper
|
||||
err error
|
||||
)
|
||||
|
||||
if vpr = o._getViper(); vpr == nil {
|
||||
return nil, nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
return nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
return nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
}
|
||||
|
||||
switch o.d {
|
||||
case ConfigCustomStatus:
|
||||
cnf := cfgcus.ModelStatus{}
|
||||
if err = vpr.UnmarshalKey(key, &cnf); err != nil {
|
||||
return nil, nil, nil, ErrorParamInvalid.Error(err)
|
||||
return nil, nil, ErrorParamInvalid.Error(err)
|
||||
} else {
|
||||
flg.updCustom(&cnf.Config)
|
||||
}
|
||||
|
||||
if cfg, err = o.d.NewFromModel(cnf); err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
} else {
|
||||
mon = &cnf.Monitor
|
||||
htc = &cnf.HTTPClient
|
||||
}
|
||||
|
||||
case ConfigCustom:
|
||||
cnf := cfgcus.Model{}
|
||||
if err = vpr.UnmarshalKey(key, &cnf); err != nil {
|
||||
return nil, nil, nil, ErrorParamInvalid.Error(err)
|
||||
return nil, nil, ErrorParamInvalid.Error(err)
|
||||
} else {
|
||||
flg.updCustom(&cnf)
|
||||
}
|
||||
|
||||
if cfg, err = o.d.NewFromModel(cnf); err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
} else {
|
||||
mon = nil
|
||||
htc = nil
|
||||
}
|
||||
|
||||
case ConfigStandardStatus:
|
||||
cnf := cfgstd.ModelStatus{}
|
||||
if err = vpr.UnmarshalKey(key, &cnf); err != nil {
|
||||
return nil, nil, nil, ErrorParamInvalid.Error(err)
|
||||
return nil, nil, ErrorParamInvalid.Error(err)
|
||||
} else {
|
||||
flg.updStandard(&cnf.Config)
|
||||
}
|
||||
|
||||
if cfg, err = o.d.NewFromModel(cnf); err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
} else {
|
||||
mon = &cnf.Monitor
|
||||
htc = &cnf.HTTPClient
|
||||
}
|
||||
|
||||
case ConfigStandard:
|
||||
cnf := cfgstd.Model{}
|
||||
if err = vpr.UnmarshalKey(key, &cnf); err != nil {
|
||||
return nil, nil, nil, ErrorParamInvalid.Error(err)
|
||||
return nil, nil, ErrorParamInvalid.Error(err)
|
||||
} else {
|
||||
flg.updStandard(&cnf)
|
||||
}
|
||||
|
||||
if cfg, err = o.d.NewFromModel(cnf); err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, err
|
||||
} else {
|
||||
mon = nil
|
||||
htc = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err = cfg.Validate(); err != nil {
|
||||
return nil, nil, nil, ErrorConfigInvalid.Error(err)
|
||||
return nil, nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
|
||||
if mon != nil {
|
||||
if err = mon.Validate(); err != nil {
|
||||
return nil, nil, nil, ErrorConfigInvalid.Error(err)
|
||||
return nil, nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
if htc != nil {
|
||||
if err = htc.Validate(); err != nil {
|
||||
return nil, nil, nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, mon, htc, nil
|
||||
return cfg, mon, nil
|
||||
}
|
||||
|
||||
func (o *componentAws) _getFlagUpdate() *_configFlag {
|
||||
|
@@ -45,7 +45,6 @@ var _defaultConfigStandard = []byte(`{
|
||||
|
||||
var _defaultConfigStandardWithStatus = []byte(`{
|
||||
"config":` + string(DefaultConfigStandard(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
|
||||
"http-client":` + string(libhtc.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `,
|
||||
"health":` + string(montps.DefaultConfig(cfgcst.JSONIndent+cfgcst.JSONIndent)) + `
|
||||
}`)
|
||||
|
||||
|
@@ -27,39 +27,33 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
libaws "github.com/nabbar/golib/aws"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
)
|
||||
|
||||
type ComponentAwsClient interface {
|
||||
cfgtps.Component
|
||||
RegisterHTTPClient(fct func() *http.Client)
|
||||
}
|
||||
|
||||
type ComponentAwsAPI interface {
|
||||
cfgtps.Component
|
||||
RegisterTLS(fct libtls.FctTLSDefault)
|
||||
}
|
||||
|
||||
type ComponentAws interface {
|
||||
ComponentAwsClient
|
||||
ComponentAwsAPI
|
||||
cfgtps.Component
|
||||
|
||||
GetAws() (libaws.AWS, error)
|
||||
GetAws() libaws.AWS
|
||||
SetAws(a libaws.AWS)
|
||||
|
||||
RegisterHTTPClient(cli libhtc.HttpClient)
|
||||
}
|
||||
|
||||
func New(drv ConfigDriver) ComponentAws {
|
||||
func New(ctx libctx.FuncContext, drv ConfigDriver) ComponentAws {
|
||||
return &componentAws{
|
||||
m: sync.RWMutex{},
|
||||
x: nil,
|
||||
x: libctx.NewConfig[uint8](ctx),
|
||||
d: drv,
|
||||
a: nil,
|
||||
p: new(atomic.Value),
|
||||
c: new(atomic.Value),
|
||||
a: new(atomic.Value),
|
||||
r: new(atomic.Value),
|
||||
s: new(atomic.Bool),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +61,8 @@ func Register(cfg libcfg.Config, key string, cpt ComponentAws) {
|
||||
cfg.ComponentSet(key, cpt)
|
||||
}
|
||||
|
||||
func RegisterNew(cfg libcfg.Config, drv ConfigDriver, key string) {
|
||||
cfg.ComponentSet(key, New(drv))
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, drv ConfigDriver, key string) {
|
||||
cfg.ComponentSet(key, New(ctx, drv))
|
||||
}
|
||||
|
||||
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentAws {
|
||||
|
@@ -27,56 +27,101 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
"sync/atomic"
|
||||
|
||||
libaws "github.com/nabbar/golib/aws"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
)
|
||||
|
||||
type componentAws struct {
|
||||
m sync.RWMutex
|
||||
x libctx.Config[uint8]
|
||||
d ConfigDriver
|
||||
p montps.FuncPool
|
||||
c func() *http.Client
|
||||
t libtls.FctTLSDefault
|
||||
a libaws.AWS
|
||||
r libreq.Request
|
||||
p *atomic.Value // montps.FuncPool
|
||||
c *atomic.Value // libhtc.HTTPClient
|
||||
a *atomic.Value // libaws.AWS
|
||||
r *atomic.Value // libreq.Request
|
||||
s *atomic.Bool // status running == true
|
||||
}
|
||||
|
||||
func (o *componentAws) RegisterHTTPClient(fct func() *http.Client) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
func (o *componentAws) RegisterHTTPClient(cli libhtc.HttpClient) {
|
||||
if cli == nil {
|
||||
cli = libhtc.GetClient()
|
||||
}
|
||||
|
||||
o.c = fct
|
||||
o.c.Store(cli)
|
||||
}
|
||||
|
||||
func (o *componentAws) RegisterTLS(fct libtls.FctTLSDefault) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
func (o *componentAws) GetAws() libaws.AWS {
|
||||
if o.s.Load() {
|
||||
return o.getAws()
|
||||
}
|
||||
|
||||
o.t = fct
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentAws) GetAws() (libaws.AWS, error) {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.a == nil {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
func (o *componentAws) getAws() libaws.AWS {
|
||||
if i := o.a.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libaws.AWS); !k {
|
||||
return nil
|
||||
} else {
|
||||
return o.a.Clone(o.x.GetContext())
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) SetAws(a libaws.AWS) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.a = a
|
||||
func (o *componentAws) SetAws(cli libaws.AWS) {
|
||||
if cli != nil {
|
||||
o.a.Store(cli)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) getPool() montps.Pool {
|
||||
if i := o.p.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(montps.FuncPool); !k {
|
||||
return nil
|
||||
} else if p := v(); p == nil {
|
||||
return nil
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) RegisterMonitorPool(fct montps.FuncPool) {
|
||||
if fct == nil {
|
||||
fct = func() montps.Pool {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
o.p.Store(fct)
|
||||
}
|
||||
|
||||
func (o *componentAws) getClient() libhtc.HttpClient {
|
||||
if i := o.c.Load(); i == nil {
|
||||
return libhtc.GetClient()
|
||||
} else if v, k := i.(libhtc.HttpClient); !k {
|
||||
return libhtc.GetClient()
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) getRequest() libreq.Request {
|
||||
if i := o.r.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libreq.Request); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) setRequest(req libreq.Request) {
|
||||
if req != nil {
|
||||
o.r.Store(req)
|
||||
}
|
||||
}
|
||||
|
@@ -31,38 +31,17 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
|
||||
libaws "github.com/nabbar/golib/aws"
|
||||
libmon "github.com/nabbar/golib/monitor"
|
||||
moninf "github.com/nabbar/golib/monitor/info"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultNameMonitor = "AWS Client"
|
||||
)
|
||||
|
||||
func (o *componentAws) RegisterMonitorPool(fct montps.FuncPool) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.p = fct
|
||||
}
|
||||
|
||||
func (o *componentAws) _getMonitorPool() montps.Pool {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.p == nil {
|
||||
return nil
|
||||
} else if p := o.p(); p == nil {
|
||||
return nil
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentAws) _registerMonitor(opt *libreq.OptionsHealth, aws libaws.Config) error {
|
||||
var (
|
||||
e error
|
||||
@@ -73,7 +52,7 @@ func (o *componentAws) _registerMonitor(opt *libreq.OptionsHealth, aws libaws.Co
|
||||
vrs = o._getVersion()
|
||||
)
|
||||
|
||||
if o._getMonitorPool() == nil {
|
||||
if o.getPool() == nil {
|
||||
return nil
|
||||
} else if len(key) < 1 {
|
||||
return ErrorComponentNotInitialized.Error(nil)
|
||||
@@ -133,10 +112,7 @@ func (o *componentAws) _registerMonitor(opt *libreq.OptionsHealth, aws libaws.Co
|
||||
}
|
||||
|
||||
func (o *componentAws) _getEndpoint(opt *libreq.OptionsHealth, aws libaws.Config) string {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.r != nil && len(opt.Endpoint) > 0 {
|
||||
if req := o.getRequest(); req != nil && len(opt.Endpoint) > 0 {
|
||||
return opt.Endpoint
|
||||
} else {
|
||||
return aws.GetEndpoint().Host
|
||||
@@ -157,7 +133,7 @@ func (o *componentAws) _newMonitor(inf montps.Info) (montps.Monitor, error) {
|
||||
func (o *componentAws) _getMonitor(key string, inf montps.Info) montps.Monitor {
|
||||
var (
|
||||
mon libmon.Monitor
|
||||
pol = o._getMonitorPool()
|
||||
pol = o.getPool()
|
||||
)
|
||||
|
||||
if pol == nil {
|
||||
@@ -175,7 +151,7 @@ func (o *componentAws) _getMonitor(key string, inf montps.Info) montps.Monitor {
|
||||
}
|
||||
|
||||
func (o *componentAws) _setMonitor(mon montps.Monitor) error {
|
||||
var pol = o._getMonitorPool()
|
||||
var pol = o.getPool()
|
||||
|
||||
if pol == nil {
|
||||
return nil
|
||||
@@ -185,14 +161,11 @@ func (o *componentAws) _setMonitor(mon montps.Monitor) error {
|
||||
}
|
||||
|
||||
func (o *componentAws) HealthCheck(ctx context.Context) error {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if !o.IsStarted() {
|
||||
if cli := o.GetAws(); cli == nil {
|
||||
return fmt.Errorf("component not started")
|
||||
} else if o.r == nil {
|
||||
return o.a.Config().Check(ctx)
|
||||
} else if req := o.getRequest(); req == nil {
|
||||
return cli.Config().Check(ctx)
|
||||
} else {
|
||||
return o.r.HealthCheck(ctx)
|
||||
return req.HealthCheck(ctx)
|
||||
}
|
||||
}
|
||||
|
@@ -29,9 +29,8 @@ package database
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nabbar/golib/database/gorm"
|
||||
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfvbr "github.com/spf13/viper"
|
||||
@@ -159,8 +158,8 @@ func (o *componentDatabase) _runCli() error {
|
||||
var (
|
||||
err error
|
||||
prt = ErrorComponentReload
|
||||
dbo gorm.Database
|
||||
cfg *gorm.Config
|
||||
dbo libdbs.Database
|
||||
cfg *libdbs.Config
|
||||
)
|
||||
|
||||
if !o.IsStarted() {
|
||||
@@ -171,7 +170,7 @@ func (o *componentDatabase) _runCli() error {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
if dbo, err = gorm.New(cfg); err != nil {
|
||||
if dbo, err = libdbs.New(cfg); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
|
@@ -27,12 +27,11 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
|
||||
"github.com/nabbar/golib/database/gorm"
|
||||
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
spfvpr "github.com/spf13/viper"
|
||||
)
|
||||
@@ -109,10 +108,10 @@ func (o *componentDatabase) RegisterFlag(Command *spfcbr.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentDatabase) _getConfig() (*gorm.Config, error) {
|
||||
func (o *componentDatabase) _getConfig() (*libdbs.Config, error) {
|
||||
var (
|
||||
key string
|
||||
cfg gorm.Config
|
||||
cfg libdbs.Config
|
||||
vpr libvpr.Viper
|
||||
err error
|
||||
)
|
||||
@@ -121,9 +120,9 @@ func (o *componentDatabase) _getConfig() (*gorm.Config, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
@@ -131,7 +130,7 @@ func (o *componentDatabase) _getConfig() (*gorm.Config, error) {
|
||||
cfg.RegisterContext(o.x.GetContext)
|
||||
|
||||
if val := vpr.GetString(key + ".driver"); val != "" {
|
||||
cfg.Driver = gorm.DriverFromString(val)
|
||||
cfg.Driver = libdbs.DriverFromString(val)
|
||||
}
|
||||
if val := vpr.GetString(key + ".name"); val != "" {
|
||||
cfg.Name = val
|
||||
|
@@ -30,11 +30,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
)
|
||||
|
||||
type ComponentDatabase interface {
|
||||
|
@@ -30,9 +30,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libdbs "github.com/nabbar/golib/database/gorm"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
)
|
||||
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package head
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
librtr "github.com/nabbar/golib/router/header"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -48,9 +50,9 @@ func (o *componentHead) _getConfig() (*librtr.HeadersConfig, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
|
@@ -29,10 +29,9 @@ package head
|
||||
import (
|
||||
"sync"
|
||||
|
||||
librtr "github.com/nabbar/golib/router/header"
|
||||
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
librtr "github.com/nabbar/golib/router/header"
|
||||
)
|
||||
|
||||
type ComponentHead interface {
|
||||
|
@@ -29,9 +29,8 @@ package head
|
||||
import (
|
||||
"sync"
|
||||
|
||||
librtr "github.com/nabbar/golib/router/header"
|
||||
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
librtr "github.com/nabbar/golib/router/header"
|
||||
)
|
||||
|
||||
type componentHead struct {
|
||||
|
@@ -29,9 +29,8 @@ package http
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
|
||||
htpool "github.com/nabbar/golib/httpserver/pool"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -51,9 +50,9 @@ func (o *componentHttp) _getConfig() (*htpool.Config, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
|
171
config/components/httpcli/client.go
Normal file
171
config/components/httpcli/client.go
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfvbr "github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func (o *componentHttpClient) _getKey() string {
|
||||
if i, l := o.x.Load(keyCptKey); !l {
|
||||
return ""
|
||||
} else if i == nil {
|
||||
return ""
|
||||
} else if v, k := i.(string); !k {
|
||||
return ""
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getFctVpr() libvpr.FuncViper {
|
||||
if i, l := o.x.Load(keyFctViper); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
return nil
|
||||
} else if f, k := i.(libvpr.FuncViper); !k {
|
||||
return nil
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getViper() libvpr.Viper {
|
||||
if f := o._getFctVpr(); f == nil {
|
||||
return nil
|
||||
} else if v := f(); v == nil {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getSPFViper() *spfvbr.Viper {
|
||||
if f := o._getViper(); f == nil {
|
||||
return nil
|
||||
} else if v := f.Viper(); v == nil {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getFctCpt() cfgtps.FuncCptGet {
|
||||
if i, l := o.x.Load(keyFctGetCpt); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
return nil
|
||||
} else if f, k := i.(cfgtps.FuncCptGet); !k {
|
||||
return nil
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getVersion() libver.Version {
|
||||
if i, l := o.x.Load(keyCptVersion); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libver.Version); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
|
||||
if o.IsStarted() {
|
||||
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
|
||||
} else {
|
||||
return o._getFctEvt(keyFctStaBef), o._getFctEvt(keyFctStaAft)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
|
||||
if i, l := o.x.Load(key); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
return nil
|
||||
} else if f, k := i.(cfgtps.FuncCptEvent); !k {
|
||||
return nil
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _runFct(fct func(cpt cfgtps.Component) error) error {
|
||||
if fct != nil {
|
||||
return fct(o)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _runCli() error {
|
||||
var (
|
||||
err error
|
||||
prt = ErrorComponentReload
|
||||
dns htcdns.DNSMapper
|
||||
cfg *htcdns.Config
|
||||
)
|
||||
|
||||
if !o.IsStarted() {
|
||||
prt = ErrorComponentStart
|
||||
}
|
||||
|
||||
if cfg, err = o._getConfig(); err != nil {
|
||||
return prt.Error(err)
|
||||
} else if dns = cfg.New(o.x.GetContext(), o.getRootCA); dns == nil {
|
||||
return prt.Error(fmt.Errorf("cannot create DNS Mapper"))
|
||||
}
|
||||
|
||||
o.setConfig(*cfg)
|
||||
o.setDNSMapper(dns)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _run() error {
|
||||
fb, fa := o._getFct()
|
||||
|
||||
if err := o._runFct(fb); err != nil {
|
||||
return err
|
||||
} else if err = o._runCli(); err != nil {
|
||||
return err
|
||||
} else if err = o._runFct(fa); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
130
config/components/httpcli/component.go
Normal file
130
config/components/httpcli/component.go
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
ComponentType = "tls"
|
||||
|
||||
keyCptKey = iota + 1
|
||||
keyCptDependencies
|
||||
keyFctViper
|
||||
keyFctGetCpt
|
||||
keyCptVersion
|
||||
keyCptLogger
|
||||
keyFctStaBef
|
||||
keyFctStaAft
|
||||
keyFctRelBef
|
||||
keyFctRelAft
|
||||
keyFctMonitorPool
|
||||
)
|
||||
|
||||
func (o *componentHttpClient) Type() string {
|
||||
return ComponentType
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
|
||||
o.x.Store(keyCptKey, key)
|
||||
o.x.Store(keyFctGetCpt, get)
|
||||
o.x.Store(keyFctViper, vpr)
|
||||
o.x.Store(keyCptVersion, vrs)
|
||||
o.x.Store(keyCptLogger, log)
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) RegisterFuncStart(before, after cfgtps.FuncCptEvent) {
|
||||
o.x.Store(keyFctStaBef, before)
|
||||
o.x.Store(keyFctStaAft, after)
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) RegisterFuncReload(before, after cfgtps.FuncCptEvent) {
|
||||
o.x.Store(keyFctRelBef, before)
|
||||
o.x.Store(keyFctRelAft, after)
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) IsStarted() bool {
|
||||
return o.getDNSMapper() != nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) IsRunning() bool {
|
||||
return o.IsStarted()
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Start() error {
|
||||
return o._run()
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Reload() error {
|
||||
return o._run()
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Stop() {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Dependencies() []string {
|
||||
var def = make([]string, 0)
|
||||
|
||||
if o == nil {
|
||||
return def
|
||||
} else if o.x == nil {
|
||||
return def
|
||||
} else if i, l := o.x.Load(keyCptDependencies); !l {
|
||||
return def
|
||||
} else if v, k := i.([]string); !k {
|
||||
return def
|
||||
} else if len(v) > 0 {
|
||||
return v
|
||||
} else {
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) SetDependencies(d []string) error {
|
||||
if o.x == nil {
|
||||
return ErrorComponentNotInitialized.Error(nil)
|
||||
} else {
|
||||
o.x.Store(keyCptDependencies, d)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) getLogger() liblog.Logger {
|
||||
if i, l := o.x.Load(keyCptLogger); !l {
|
||||
return nil
|
||||
} else if v, k := i.(liblog.FuncLog); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v()
|
||||
}
|
||||
}
|
62
config/components/httpcli/config.go
Normal file
62
config/components/httpcli/config.go
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func (o *componentHttpClient) RegisterFlag(Command *spfcbr.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) _getConfig() (*htcdns.Config, error) {
|
||||
var (
|
||||
key string
|
||||
cfg htcdns.Config
|
||||
vpr libvpr.Viper
|
||||
err error
|
||||
)
|
||||
|
||||
if vpr = o._getViper(); vpr == nil {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
} else if err = cfg.Validate(); err != nil {
|
||||
return nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
39
config/components/httpcli/default.go
Normal file
39
config/components/httpcli/default.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
)
|
||||
|
||||
func DefaultConfig(indent string) []byte {
|
||||
return htcdns.DefaultConfig(indent)
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) DefaultConfig(indent string) []byte {
|
||||
return htcdns.DefaultConfig(indent)
|
||||
}
|
103
config/components/httpcli/dns.go
Normal file
103
config/components/httpcli/dns.go
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
)
|
||||
|
||||
func (o *componentHttpClient) Add(endpoint string, ip string) {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
d.Add(endpoint, ip)
|
||||
o.setDNSMapper(d)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Get(endpoint string) string {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.Get(endpoint)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Del(endpoint string) {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
d.Del(endpoint)
|
||||
o.setDNSMapper(d)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.DialContext(ctx, network, address)
|
||||
}
|
||||
|
||||
return nil, ErrorComponentNotInitialized.Error()
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Transport(cfg htcdns.TransportConfig) *http.Transport {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.Transport(cfg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Client(cfg htcdns.TransportConfig) *http.Client {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.Client(cfg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) DefaultTransport() *http.Transport {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.DefaultTransport()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) DefaultClient() *http.Client {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
return d.DefaultClient()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) TimeCleaner(ctx context.Context, dur time.Duration) {
|
||||
if d := o.getDNSMapper(); d != nil {
|
||||
d.TimeCleaner(ctx, dur)
|
||||
}
|
||||
}
|
69
config/components/httpcli/errors.go
Normal file
69
config/components/httpcli/errors.go
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrorParamEmpty liberr.CodeError = iota + libcfg.MinErrorComponentHttpCli
|
||||
ErrorParamInvalid
|
||||
ErrorComponentNotInitialized
|
||||
ErrorConfigInvalid
|
||||
ErrorComponentStart
|
||||
ErrorComponentReload
|
||||
)
|
||||
|
||||
func init() {
|
||||
if liberr.ExistInMapMessage(ErrorParamEmpty) {
|
||||
panic(fmt.Errorf("error code collision with package golib/config/components/httpcli"))
|
||||
}
|
||||
liberr.RegisterIdFctMessage(ErrorParamEmpty, getMessage)
|
||||
}
|
||||
|
||||
func getMessage(code liberr.CodeError) (message string) {
|
||||
switch code {
|
||||
case ErrorParamEmpty:
|
||||
return "at least one given parameters is empty"
|
||||
case ErrorParamInvalid:
|
||||
return "at least one given parameters is invalid"
|
||||
case ErrorComponentNotInitialized:
|
||||
return "this component seems to not be correctly initialized"
|
||||
case ErrorConfigInvalid:
|
||||
return "server invalid config"
|
||||
case ErrorComponentStart:
|
||||
return "cannot start http client / dns mapper with config"
|
||||
case ErrorComponentReload:
|
||||
return "cannot update http client / dns mapper with new config"
|
||||
}
|
||||
|
||||
return liberr.NullMessage
|
||||
}
|
85
config/components/httpcli/interface.go
Normal file
85
config/components/httpcli/interface.go
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
)
|
||||
|
||||
type ComponentHTTPClient interface {
|
||||
cfgtps.Component
|
||||
htcdns.DNSMapper
|
||||
|
||||
Config() htcdns.Config
|
||||
SetDefault()
|
||||
SetAsDefaultHTTPClient(flag bool)
|
||||
}
|
||||
|
||||
func New(ctx libctx.FuncContext, defCARoot libtls.FctRootCA, isDeftHTTPClient bool) ComponentHTTPClient {
|
||||
c := &componentHttpClient{
|
||||
x: libctx.NewConfig[uint8](ctx),
|
||||
c: new(atomic.Value),
|
||||
d: new(atomic.Value),
|
||||
f: new(atomic.Value),
|
||||
s: new(atomic.Bool),
|
||||
}
|
||||
|
||||
if defCARoot == nil {
|
||||
defCARoot = func() []string {
|
||||
return make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
c.f.Store(defCARoot)
|
||||
c.s.Store(isDeftHTTPClient)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func Register(cfg libcfg.Config, key string, cpt ComponentHTTPClient) {
|
||||
cfg.ComponentSet(key, cpt)
|
||||
}
|
||||
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, defCARoot libtls.FctRootCA, isDeftHTTPClient bool) {
|
||||
cfg.ComponentSet(key, New(ctx, defCARoot, isDeftHTTPClient))
|
||||
}
|
||||
|
||||
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentHTTPClient {
|
||||
if c := getCpt(key); c == nil {
|
||||
return nil
|
||||
} else if h, ok := c.(ComponentHTTPClient); !ok {
|
||||
return nil
|
||||
} else {
|
||||
return h
|
||||
}
|
||||
}
|
98
config/components/httpcli/model.go
Normal file
98
config/components/httpcli/model.go
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
)
|
||||
|
||||
type componentHttpClient struct {
|
||||
x libctx.Config[uint8]
|
||||
c *atomic.Value // htcdns.Config
|
||||
d *atomic.Value // htcdns.DNSMapper
|
||||
f *atomic.Value // FuncDefaultCARoot
|
||||
s *atomic.Bool // is Default at start / update
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) getRootCA() []string {
|
||||
if i := o.f.Load(); i == nil {
|
||||
return make([]string, 0)
|
||||
} else if v, k := i.(libtls.FctRootCA); !k {
|
||||
return make([]string, 0)
|
||||
} else if r := v(); len(r) < 1 {
|
||||
return make([]string, 0)
|
||||
} else {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) getDNSMapper() htcdns.DNSMapper {
|
||||
if i := o.d.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(htcdns.DNSMapper); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) setDNSMapper(dns htcdns.DNSMapper) {
|
||||
if o.s.Load() {
|
||||
defer o.SetDefault()
|
||||
}
|
||||
|
||||
if dns != nil {
|
||||
o.d.Store(dns)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) Config() htcdns.Config {
|
||||
if i := o.c.Load(); i == nil {
|
||||
return htcdns.Config{}
|
||||
} else if v, k := i.(*htcdns.Config); !k {
|
||||
return htcdns.Config{}
|
||||
} else {
|
||||
return *v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) setConfig(cfg htcdns.Config) {
|
||||
o.c.Store(&cfg)
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) SetDefault() {
|
||||
libhtc.SetDefaultDNSMapper(o.getDNSMapper())
|
||||
}
|
||||
|
||||
func (o *componentHttpClient) SetAsDefaultHTTPClient(flag bool) {
|
||||
o.s.Store(flag)
|
||||
}
|
34
config/components/httpcli/monitor.go
Normal file
34
config/components/httpcli/monitor.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
)
|
||||
|
||||
func (o *componentHttpClient) RegisterMonitorPool(fct montps.FuncPool) {
|
||||
}
|
@@ -27,6 +27,8 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
lbldap "github.com/nabbar/golib/ldap"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -48,13 +50,11 @@ func (o *componentLDAP) _getConfig() (*lbldap.Config, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
if err = cfg.Validate(); err != nil {
|
||||
} else if err = cfg.Validate(); err != nil {
|
||||
return nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
logcfg "github.com/nabbar/golib/logger/config"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -82,9 +84,9 @@ func (o *componentLog) _getConfig() (*logcfg.Options, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package mail
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libmail "github.com/nabbar/golib/mail"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -90,9 +92,9 @@ func (o *componentMail) _getConfig() (*libmail.Config, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
|
@@ -29,8 +29,6 @@ package request
|
||||
import (
|
||||
"context"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
cpttls "github.com/nabbar/golib/config/components/tls"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
@@ -39,9 +37,6 @@ import (
|
||||
)
|
||||
|
||||
func (o *componentRequest) _getKey() string {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyCptKey); !l {
|
||||
return ""
|
||||
} else if i == nil {
|
||||
@@ -54,9 +49,6 @@ func (o *componentRequest) _getKey() string {
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getFctVpr() libvpr.FuncViper {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyFctViper); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -89,9 +81,6 @@ func (o *componentRequest) _getSPFViper() *spfvbr.Viper {
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getFctCpt() cfgtps.FuncCptGet {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyFctGetCpt); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -104,16 +93,10 @@ func (o *componentRequest) _getFctCpt() cfgtps.FuncCptGet {
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getContext() context.Context {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
return o.x.GetContext()
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getVersion() libver.Version {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(keyCptVersion); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -125,23 +108,6 @@ func (o *componentRequest) _getVersion() libver.Version {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) _GetTLS() libtls.TLSConfig {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.t == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if i := cpttls.Load(o._getFctCpt(), o.t); i == nil {
|
||||
return nil
|
||||
} else if tls := i.GetTLS(); tls == nil {
|
||||
return nil
|
||||
} else {
|
||||
return tls
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent) {
|
||||
if o.IsStarted() {
|
||||
return o._getFctEvt(keyFctRelBef), o._getFctEvt(keyFctRelAft)
|
||||
@@ -151,9 +117,6 @@ func (o *componentRequest) _getFct() (cfgtps.FuncCptEvent, cfgtps.FuncCptEvent)
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getFctEvt(key uint8) cfgtps.FuncCptEvent {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if i, l := o.x.Load(key); !l {
|
||||
return nil
|
||||
} else if i == nil {
|
||||
@@ -185,29 +148,27 @@ func (o *componentRequest) _runCli() error {
|
||||
if !o.IsStarted() {
|
||||
prt = ErrorComponentStart
|
||||
} else {
|
||||
req = o.r
|
||||
req = o.getRequest()
|
||||
}
|
||||
|
||||
if cfg, err = o._getConfig(); err != nil {
|
||||
return prt.Error(err)
|
||||
}
|
||||
|
||||
cfg.SetDefaultTLS(o._GetTLS)
|
||||
cfg.SetDefaultLog(o.getLogger)
|
||||
|
||||
if req != nil {
|
||||
if req, e = cfg.Update(o.x.GetContext, req); err != nil {
|
||||
return prt.Error(e)
|
||||
}
|
||||
req.RegisterHTTPClient(o.getClient())
|
||||
} else {
|
||||
if req, e = cfg.New(o.x.GetContext); err != nil {
|
||||
if req, e = cfg.New(o.x.GetContext, o.getClient()); err != nil {
|
||||
return prt.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
o.m.Lock()
|
||||
o.r = req
|
||||
o.m.Unlock()
|
||||
o.setRequest(req)
|
||||
|
||||
if e = o._registerMonitor(cfg); e != nil {
|
||||
return prt.Error(e)
|
||||
|
@@ -56,17 +56,6 @@ func (o *componentRequest) Type() string {
|
||||
}
|
||||
|
||||
func (o *componentRequest) Init(key string, ctx libctx.FuncContext, get cfgtps.FuncCptGet, vpr libvpr.FuncViper, vrs libver.Version, log liblog.FuncLog) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
if o.x == nil {
|
||||
o.x = libctx.NewConfig[uint8](ctx)
|
||||
} else {
|
||||
x := libctx.NewConfig[uint8](ctx)
|
||||
x.Merge(o.x)
|
||||
o.x = x
|
||||
}
|
||||
|
||||
o.x.Store(keyCptKey, key)
|
||||
o.x.Store(keyFctGetCpt, get)
|
||||
o.x.Store(keyFctViper, vpr)
|
||||
@@ -85,9 +74,6 @@ func (o *componentRequest) RegisterFuncReload(before, after cfgtps.FuncCptEvent)
|
||||
}
|
||||
|
||||
func (o *componentRequest) IsStarted() bool {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
return o != nil && o.r != nil
|
||||
}
|
||||
|
||||
@@ -104,23 +90,14 @@ func (o *componentRequest) Reload() error {
|
||||
}
|
||||
|
||||
func (o *componentRequest) Stop() {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.r = nil
|
||||
return
|
||||
o.setRequest(nil)
|
||||
}
|
||||
|
||||
func (o *componentRequest) Dependencies() []string {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
var def = []string{cpttls.ComponentType}
|
||||
|
||||
if o == nil {
|
||||
return def
|
||||
} else if len(o.t) > 0 {
|
||||
def = []string{o.t}
|
||||
}
|
||||
|
||||
if o.x == nil {
|
||||
@@ -137,9 +114,6 @@ func (o *componentRequest) Dependencies() []string {
|
||||
}
|
||||
|
||||
func (o *componentRequest) SetDependencies(d []string) error {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.x == nil {
|
||||
return ErrorComponentNotInitialized.Error(nil)
|
||||
} else {
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -48,13 +50,11 @@ func (o *componentRequest) _getConfig() (*libreq.Options, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
if err = cfg.Validate(); err != nil {
|
||||
} else if err = cfg.Validate(); err != nil {
|
||||
return nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
|
||||
|
@@ -31,13 +31,11 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
cfgcst "github.com/nabbar/golib/config/const"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
moncfg "github.com/nabbar/golib/monitor/types"
|
||||
)
|
||||
|
||||
var _defaultConfig = []byte(`{
|
||||
"endpoint":"https://endpoint.example.com/path",
|
||||
"http_client": ` + string(libhtc.DefaultConfig(cfgcst.JSONIndent)) + `,
|
||||
"auth": {
|
||||
"basic":{
|
||||
"enable": false,
|
||||
|
@@ -27,36 +27,43 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
libcfg "github.com/nabbar/golib/config"
|
||||
cfgtps "github.com/nabbar/golib/config/types"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
)
|
||||
|
||||
type ComponentRequest interface {
|
||||
cfgtps.Component
|
||||
|
||||
SetDefaultTLS(key string)
|
||||
Request() (libreq.Request, error)
|
||||
SetHTTPClient(cli libhtc.HttpClient)
|
||||
Request() libreq.Request
|
||||
}
|
||||
|
||||
func New(ctx libctx.FuncContext, tls string) ComponentRequest {
|
||||
return &componentRequest{
|
||||
m: sync.RWMutex{},
|
||||
func New(ctx libctx.FuncContext, cli libhtc.HttpClient) ComponentRequest {
|
||||
o := &componentRequest{
|
||||
x: libctx.NewConfig[uint8](ctx),
|
||||
r: nil,
|
||||
t: tls,
|
||||
r: new(atomic.Value),
|
||||
c: new(atomic.Value),
|
||||
p: new(atomic.Value),
|
||||
}
|
||||
|
||||
if cli != nil {
|
||||
o.c.Store(cli)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func Register(cfg libcfg.Config, key string, cpt ComponentRequest) {
|
||||
cfg.ComponentSet(key, cpt)
|
||||
}
|
||||
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key, tls string) {
|
||||
cfg.ComponentSet(key, New(ctx, tls))
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, cli libhtc.HttpClient) {
|
||||
cfg.ComponentSet(key, New(ctx, cli))
|
||||
}
|
||||
|
||||
func Load(getCpt cfgtps.FuncCptGet, key string) ComponentRequest {
|
||||
|
@@ -27,31 +27,86 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libreq "github.com/nabbar/golib/request"
|
||||
)
|
||||
|
||||
type componentRequest struct {
|
||||
m sync.RWMutex
|
||||
x libctx.Config[uint8]
|
||||
r libreq.Request
|
||||
t string
|
||||
p montps.FuncPool
|
||||
r *atomic.Value // libreq.Request
|
||||
c *atomic.Value // libhtc.HttpClient
|
||||
p *atomic.Value // montps.FuncPool
|
||||
}
|
||||
|
||||
func (o *componentRequest) SetDefaultTLS(key string) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.t = key
|
||||
func (o *componentRequest) SetHTTPClient(cli libhtc.HttpClient) {
|
||||
o.setClient(cli)
|
||||
}
|
||||
|
||||
func (o *componentRequest) Request() (libreq.Request, error) {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
return o.r.Clone()
|
||||
func (o *componentRequest) Request() libreq.Request {
|
||||
return o.getRequest()
|
||||
}
|
||||
|
||||
func (o *componentRequest) RegisterMonitorPool(fct montps.FuncPool) {
|
||||
o.setPool(fct)
|
||||
}
|
||||
|
||||
func (o *componentRequest) getRequest() libreq.Request {
|
||||
if i := o.r.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libreq.Request); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) setRequest(req libreq.Request) {
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
o.r.Store(req)
|
||||
}
|
||||
|
||||
func (o *componentRequest) getClient() libhtc.HttpClient {
|
||||
if i := o.c.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(libhtc.HttpClient); !k {
|
||||
return nil
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) setClient(cli libhtc.HttpClient) {
|
||||
if cli == nil {
|
||||
return
|
||||
}
|
||||
|
||||
o.c.Store(cli)
|
||||
}
|
||||
|
||||
func (o *componentRequest) getPool() montps.Pool {
|
||||
if i := o.p.Load(); i == nil {
|
||||
return nil
|
||||
} else if v, k := i.(montps.FuncPool); !k {
|
||||
return nil
|
||||
} else if p := v(); p == nil {
|
||||
return nil
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) setPool(fct montps.FuncPool) {
|
||||
if fct == nil {
|
||||
fct = func() montps.Pool {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
o.p.Store(fct)
|
||||
}
|
||||
|
@@ -34,26 +34,6 @@ import (
|
||||
libver "github.com/nabbar/golib/version"
|
||||
)
|
||||
|
||||
func (o *componentRequest) RegisterMonitorPool(fct montps.FuncPool) {
|
||||
o.m.Lock()
|
||||
defer o.m.Unlock()
|
||||
|
||||
o.p = fct
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getMonitorPool() montps.Pool {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.p == nil {
|
||||
return nil
|
||||
} else if p := o.p(); p == nil {
|
||||
return nil
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
func (o *componentRequest) _registerMonitor(cfg *libreq.Options) error {
|
||||
var (
|
||||
e error
|
||||
@@ -63,7 +43,7 @@ func (o *componentRequest) _registerMonitor(cfg *libreq.Options) error {
|
||||
ctx = o._getContext()
|
||||
)
|
||||
|
||||
if o._getMonitorPool() == nil {
|
||||
if o.getPool() == nil {
|
||||
return nil
|
||||
} else if len(key) < 1 {
|
||||
return ErrorComponentNotInitialized.Error(nil)
|
||||
@@ -107,15 +87,13 @@ func (o *componentRequest) _registerMonitor(cfg *libreq.Options) error {
|
||||
}
|
||||
|
||||
func (o *componentRequest) _newMonitor(ctx context.Context, vrs libver.Version) (montps.Monitor, error) {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
return o.r.Monitor(ctx, vrs)
|
||||
return o.getRequest().Monitor(ctx, vrs)
|
||||
}
|
||||
|
||||
func (o *componentRequest) _getMonitor(key string) montps.Monitor {
|
||||
var (
|
||||
mon montps.Monitor
|
||||
pol = o._getMonitorPool()
|
||||
pol = o.getPool()
|
||||
)
|
||||
|
||||
if pol == nil {
|
||||
@@ -127,7 +105,7 @@ func (o *componentRequest) _getMonitor(key string) montps.Monitor {
|
||||
}
|
||||
|
||||
func (o *componentRequest) _setMonitor(mon montps.Monitor) error {
|
||||
var pol = o._getMonitorPool()
|
||||
var pol = o.getPool()
|
||||
|
||||
if pol == nil {
|
||||
return nil
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libmon "github.com/nabbar/golib/monitor/types"
|
||||
smtpcf "github.com/nabbar/golib/smtp/config"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
@@ -67,9 +69,9 @@ func (o *componentSmtp) _getConfig() (smtpcf.Config, *libmon.Config, error) {
|
||||
return nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,8 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libvpr "github.com/nabbar/golib/viper"
|
||||
spfcbr "github.com/spf13/cobra"
|
||||
@@ -48,13 +50,11 @@ func (o *componentTls) _getConfig() (*libtls.Config, error) {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
} else if key = o._getKey(); len(key) < 1 {
|
||||
return nil, ErrorComponentNotInitialized.Error(nil)
|
||||
}
|
||||
|
||||
if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
} else if !vpr.Viper().IsSet(key) {
|
||||
return nil, ErrorParamInvalid.Error(fmt.Errorf("missing config key '%s'", key))
|
||||
} else if e := vpr.UnmarshalKey(key, &cfg); e != nil {
|
||||
return nil, ErrorParamInvalid.Error(e)
|
||||
}
|
||||
|
||||
if err = cfg.Validate(); err != nil {
|
||||
} else if err = cfg.Validate(); err != nil {
|
||||
return nil, ErrorConfigInvalid.Error(err)
|
||||
}
|
||||
|
||||
|
@@ -60,9 +60,9 @@ func getMessage(code liberr.CodeError) (message string) {
|
||||
case ErrorConfigInvalid:
|
||||
return "server invalid config"
|
||||
case ErrorComponentStart:
|
||||
return "cannot open database connection with config"
|
||||
return "cannot initiate new TLSConfig with config"
|
||||
case ErrorComponentReload:
|
||||
return "cannot update database connection with new config"
|
||||
return "cannot update TLSConfig with new config"
|
||||
}
|
||||
|
||||
return liberr.NullMessage
|
||||
|
@@ -35,8 +35,6 @@ import (
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
)
|
||||
|
||||
type FuncDefaultCARoot func() []string
|
||||
|
||||
type ComponentTlS interface {
|
||||
cfgtps.Component
|
||||
Config() *libtls.Config
|
||||
@@ -44,12 +42,13 @@ type ComponentTlS interface {
|
||||
SetTLS(tls libtls.TLSConfig)
|
||||
}
|
||||
|
||||
func New(ctx libctx.FuncContext, defCARoot FuncDefaultCARoot) ComponentTlS {
|
||||
func New(ctx libctx.FuncContext, defCARoot libtls.FctRootCA) ComponentTlS {
|
||||
return &componentTls{
|
||||
m: sync.RWMutex{},
|
||||
x: libctx.NewConfig[uint8](ctx),
|
||||
t: nil,
|
||||
c: nil,
|
||||
f: defCARoot,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ func Register(cfg libcfg.Config, key string, cpt ComponentTlS) {
|
||||
cfg.ComponentSet(key, cpt)
|
||||
}
|
||||
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, defCARoot FuncDefaultCARoot) {
|
||||
func RegisterNew(ctx libctx.FuncContext, cfg libcfg.Config, key string, defCARoot libtls.FctRootCA) {
|
||||
cfg.ComponentSet(key, New(ctx, defCARoot))
|
||||
}
|
||||
|
||||
|
@@ -38,7 +38,7 @@ type componentTls struct {
|
||||
x libctx.Config[uint8]
|
||||
t libtls.TLSConfig
|
||||
c *libtls.Config
|
||||
f FuncDefaultCARoot
|
||||
f libtls.FctRootCA
|
||||
}
|
||||
|
||||
func (o *componentTls) Config() *libtls.Config {
|
||||
|
@@ -48,7 +48,8 @@ const (
|
||||
MinErrorComponentDatabase = MinErrorComponentAws + 10
|
||||
MinErrorComponentHead = MinErrorComponentDatabase + 10
|
||||
MinErrorComponentHttp = MinErrorComponentHead + 10
|
||||
MinErrorComponentLdap = MinErrorComponentHttp + 10
|
||||
MinErrorComponentHttpCli = MinErrorComponentHttp + 10
|
||||
MinErrorComponentLdap = MinErrorComponentHttpCli + 10
|
||||
MinErrorComponentLog = MinErrorComponentLdap + 10
|
||||
MinErrorComponentMail = MinErrorComponentLog + 10
|
||||
MinErrorComponentNats = MinErrorComponentMail + 10
|
||||
|
@@ -27,8 +27,11 @@
|
||||
package crypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
type reader struct {
|
||||
@@ -77,7 +80,11 @@ func (o *crt) ReaderHex(r io.Reader) io.Reader {
|
||||
|
||||
if n, err = r.Read(b); err != nil {
|
||||
return 0, err
|
||||
} else if a, err = o.DecodeHex(b[:n]); err != nil {
|
||||
} else if bytes.HasSuffix(b[:n], []byte{libsck.EOL}) {
|
||||
n = n - len([]byte{libsck.EOL})
|
||||
}
|
||||
|
||||
if a, err = o.DecodeHex(b[:n]); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
copy(p, a)
|
||||
|
@@ -45,11 +45,12 @@ const (
|
||||
MinPkgDatabaseKVTbl = baseSub + MinPkgDatabaseKVMap
|
||||
MinPkgDatabaseKVItm = baseSub + MinPkgDatabaseKVTbl
|
||||
|
||||
MinPkgFileProgress = baseInc + MinPkgDatabaseGorm
|
||||
MinPkgFTPClient = baseInc + MinPkgFileProgress
|
||||
MinPkgHttpCli = baseInc + MinPkgFTPClient
|
||||
MinPkgFileProgress = baseInc + MinPkgDatabaseGorm
|
||||
MinPkgFTPClient = baseInc + MinPkgFileProgress
|
||||
MinPkgHttpCli = baseInc + MinPkgFTPClient
|
||||
MinPkgHttpCliDNSMapper = baseSub + MinPkgHttpCli
|
||||
|
||||
MinPkgHttpServer = baseInc + MinPkgHttpCli
|
||||
MinPkgHttpServer = baseInc + MinPkgHttpCliDNSMapper
|
||||
MinPkgHttpServerPool = baseSub + MinPkgHttpServer
|
||||
|
||||
MinPkgIOUtils = baseInc + MinPkgHttpServer
|
||||
|
90
go.mod
90
go.mod
@@ -2,24 +2,24 @@ module github.com/nabbar/golib
|
||||
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.5
|
||||
toolchain go1.21.6
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.50.10
|
||||
github.com/aws/aws-sdk-go-v2 v1.24.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.26.6
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.16.16
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.28.7
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.48.1
|
||||
github.com/aws/smithy-go v1.19.0
|
||||
github.com/aws/aws-sdk-go v1.50.19
|
||||
github.com/aws/aws-sdk-go-v2 v1.25.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.0
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.0
|
||||
github.com/aws/aws-sdk-go-v2/service/iam v1.29.0
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0
|
||||
github.com/aws/smithy-go v1.20.0
|
||||
github.com/bits-and-blooms/bitset v1.13.0
|
||||
github.com/c-bata/go-prompt v0.2.6
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/fxamacker/cbor/v2 v2.5.0
|
||||
github.com/fxamacker/cbor/v2 v2.6.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/go-playground/validator/v10 v10.17.0
|
||||
github.com/go-playground/validator/v10 v10.18.0
|
||||
github.com/google/go-github/v33 v33.0.0
|
||||
github.com/hashicorp/go-hclog v1.6.2
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5
|
||||
@@ -31,9 +31,9 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nats-io/jwt/v2 v2.5.3
|
||||
github.com/nats-io/nats-server/v2 v2.10.10
|
||||
github.com/nats-io/nats.go v1.32.0
|
||||
github.com/nats-io/jwt/v2 v2.5.4
|
||||
github.com/nats-io/nats-server/v2 v2.10.11
|
||||
github.com/nats-io/nats.go v1.33.0
|
||||
github.com/nutsdb/nutsdb v0.14.3
|
||||
github.com/onsi/ginkgo/v2 v2.15.0
|
||||
github.com/onsi/gomega v1.31.1
|
||||
@@ -45,23 +45,23 @@ require (
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/viper v1.18.2
|
||||
github.com/ugorji/go/codec v1.2.12
|
||||
github.com/vbauerster/mpb/v8 v8.6.2
|
||||
github.com/vbauerster/mpb/v8 v8.7.2
|
||||
github.com/xanzy/go-gitlab v0.97.0
|
||||
github.com/xhit/go-simple-mail v2.2.2+incompatible
|
||||
github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235
|
||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/oauth2 v0.16.0
|
||||
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/oauth2 v0.17.0
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.16.0
|
||||
golang.org/x/term v0.16.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/term v0.17.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/clickhouse v0.6.0
|
||||
gorm.io/driver/mysql v1.5.2
|
||||
gorm.io/driver/postgres v1.5.4
|
||||
gorm.io/driver/sqlite v1.5.4
|
||||
gorm.io/driver/sqlserver v1.5.2
|
||||
gorm.io/gorm v1.25.6
|
||||
gorm.io/driver/mysql v1.5.4
|
||||
gorm.io/driver/postgres v1.5.6
|
||||
gorm.io/driver/sqlite v1.5.5
|
||||
gorm.io/driver/sqlserver v1.5.3
|
||||
gorm.io/gorm v1.25.7
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -78,21 +78,21 @@ require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/antlabs/stl v0.0.2 // indirect
|
||||
github.com/antlabs/timer v0.1.1 // indirect
|
||||
github.com/antlabs/timer v0.1.3 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.19.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bwmarrin/snowflake v0.3.0 // indirect
|
||||
github.com/bytedance/sonic v1.10.2 // indirect
|
||||
@@ -125,7 +125,7 @@ require (
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240130152714-0ed6a68c8d9e // indirect
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -150,7 +150,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/juju/ratelimit v1.0.2-0.20191002062651-f60b32039441 // indirect
|
||||
github.com/klauspost/compress v1.17.5 // indirect
|
||||
github.com/klauspost/compress v1.17.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
@@ -180,7 +180,7 @@ require (
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.6 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
@@ -203,14 +203,14 @@ require (
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xujiajun/mmap-go v1.0.1 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.opentelemetry.io/otel v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.22.0 // indirect
|
||||
go.opentelemetry.io/otel v1.23.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.23.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
|
203
httpcli/cli.go
203
httpcli/cli.go
@@ -28,162 +28,87 @@ package httpcli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
"golang.org/x/net/http2"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libdur "github.com/nabbar/golib/duration"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
)
|
||||
|
||||
const (
|
||||
ClientTimeout30Sec = 30 * time.Second
|
||||
ClientTimeout10Sec = 10 * time.Second
|
||||
ClientTimeout5Sec = 5 * time.Second
|
||||
ClientTimeout1Sec = 1 * time.Second
|
||||
|
||||
ClientNetworkTCP = "tcp"
|
||||
ClientNetworkUDP = "udp"
|
||||
ClientTimeout5Sec = 5 * time.Second
|
||||
)
|
||||
|
||||
var trp = new(atomic.Value)
|
||||
var (
|
||||
dns = new(atomic.Value)
|
||||
ctx context.Context
|
||||
cnl context.CancelFunc
|
||||
)
|
||||
|
||||
func init() {
|
||||
trp.Store(&http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DisableKeepAlives: false,
|
||||
DisableCompression: false,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 1,
|
||||
MaxConnsPerHost: 25,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSClientConfig: &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
MaxVersion: tls.VersionTLS13,
|
||||
func initDNSMapper() htcdns.DNSMapper {
|
||||
if cnl != nil {
|
||||
cnl()
|
||||
}
|
||||
|
||||
ctx, cnl = context.WithCancel(context.Background())
|
||||
|
||||
return htcdns.New(ctx, &htcdns.Config{
|
||||
DNSMapper: make(map[string]string),
|
||||
TimerClean: libdur.ParseDuration(3 * time.Minute),
|
||||
Transport: htcdns.TransportConfig{
|
||||
Proxy: nil,
|
||||
TLSConfig: &libtls.Config{},
|
||||
DisableHTTP2: false,
|
||||
DisableKeepAlive: false,
|
||||
DisableCompression: false,
|
||||
MaxIdleConns: 50,
|
||||
MaxIdleConnsPerHost: 5,
|
||||
MaxConnsPerHost: 25,
|
||||
TimeoutGlobal: libdur.ParseDuration(30 * time.Second),
|
||||
TimeoutKeepAlive: libdur.ParseDuration(15 * time.Second),
|
||||
TimeoutTLSHandshake: libdur.ParseDuration(10 * time.Second),
|
||||
TimeoutExpectContinue: libdur.ParseDuration(3 * time.Second),
|
||||
TimeoutIdleConn: libdur.ParseDuration(30 * time.Second),
|
||||
TimeoutResponseHeader: 0,
|
||||
},
|
||||
})
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func DefaultDNSMapper() htcdns.DNSMapper {
|
||||
if i := dns.Load(); i == nil {
|
||||
d := initDNSMapper()
|
||||
dns.Store(d)
|
||||
return d
|
||||
} else if d, k := i.(htcdns.DNSMapper); !k {
|
||||
d = initDNSMapper()
|
||||
dns.Store(d)
|
||||
return d
|
||||
} else {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
func SetDefaultDNSMapper(d htcdns.DNSMapper) {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if cnl != nil {
|
||||
cnl()
|
||||
}
|
||||
|
||||
dns.Store(d)
|
||||
}
|
||||
|
||||
type FctHttpClient func() *http.Client
|
||||
type FctHttpClientSrv func(servername string) *http.Client
|
||||
|
||||
type HttpClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
func ForceUpdateTransport(cfg *tls.Config, proxyUrl *url.URL) *http.Transport {
|
||||
t := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: cfg.Clone(),
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DisableKeepAlives: false,
|
||||
DisableCompression: false,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 1,
|
||||
MaxConnsPerHost: 25,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
}
|
||||
|
||||
if proxyUrl != nil {
|
||||
t.Proxy = http.ProxyURL(proxyUrl)
|
||||
}
|
||||
|
||||
trp.Store(t)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func GetTransport(tlsConfig *tls.Config, proxyURL *url.URL, DisableKeepAlive, DisableCompression, ForceHTTP2 bool) *http.Transport {
|
||||
var tr *http.Transport
|
||||
|
||||
if i := trp.Load(); i != nil {
|
||||
if t, k := i.(*http.Transport); k {
|
||||
tr = t.Clone()
|
||||
}
|
||||
}
|
||||
|
||||
if tr == nil {
|
||||
tr = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
DisableKeepAlives: false,
|
||||
DisableCompression: false,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 1,
|
||||
MaxConnsPerHost: 25,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
}
|
||||
}
|
||||
|
||||
tr.DisableCompression = DisableCompression
|
||||
tr.DisableKeepAlives = DisableKeepAlive
|
||||
tr.TLSClientConfig = tlsConfig.Clone()
|
||||
|
||||
if proxyURL != nil {
|
||||
tr.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
|
||||
return tr
|
||||
}
|
||||
|
||||
func SetTransportDial(tr *http.Transport, forceIp bool, netw libptc.NetworkProtocol, ip, local string) {
|
||||
var (
|
||||
dial = &net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}
|
||||
fctDial func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
)
|
||||
|
||||
if forceIp && len(local) > 0 {
|
||||
u := &url.URL{
|
||||
Host: local,
|
||||
}
|
||||
fctDial = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
dial.LocalAddr = &net.TCPAddr{
|
||||
IP: net.ParseIP(u.Hostname()),
|
||||
}
|
||||
|
||||
return dial.DialContext(ctx, netw.Code(), ip)
|
||||
}
|
||||
} else if forceIp {
|
||||
fctDial = func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return dial.DialContext(ctx, netw.Code(), ip)
|
||||
}
|
||||
} else {
|
||||
fctDial = dial.DialContext
|
||||
}
|
||||
|
||||
tr.DialContext = fctDial
|
||||
tr.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return tls.DialWithDialer(dial, network, addr, tr.TLSClientConfig)
|
||||
}
|
||||
}
|
||||
|
||||
func GetClient(tr *http.Transport, http2Tr bool, GlobalTimeout time.Duration) (*http.Client, liberr.Error) {
|
||||
if http2Tr {
|
||||
if e := http2.ConfigureTransport(tr); e != nil {
|
||||
return nil, ErrorClientTransportHttp2.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
c := &http.Client{
|
||||
Transport: tr,
|
||||
}
|
||||
|
||||
if GlobalTimeout != 0 {
|
||||
c.Timeout = GlobalTimeout
|
||||
}
|
||||
|
||||
return c, nil
|
||||
func GetClient() *http.Client {
|
||||
return DefaultDNSMapper().DefaultClient()
|
||||
}
|
||||
|
126
httpcli/dns-mapper/config.go
Normal file
126
httpcli/dns-mapper/config.go
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package dns_mapper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
libval "github.com/go-playground/validator/v10"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
cmptls "github.com/nabbar/golib/config/components/tls"
|
||||
cfgcst "github.com/nabbar/golib/config/const"
|
||||
libdur "github.com/nabbar/golib/duration"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
|
||||
type TransportConfig struct {
|
||||
Proxy *url.URL `json:"proxy,omitempty" yaml:"proxy,omitempty" toml:"proxy,omitempty" mapstructure:"proxy,omitempty"`
|
||||
TLSConfig *libtls.Config `json:"tls-config,omitempty" yaml:"tls-config,omitempty" toml:"tls-config,omitempty" mapstructure:"tls-config,omitempty"`
|
||||
|
||||
DisableHTTP2 bool `json:"disable-http2" yaml:"disable-http2" toml:"disable-http2" mapstructure:"disable-http2"`
|
||||
DisableKeepAlive bool `json:"disable-keepalive" yaml:"disable-keepalive" toml:"disable-keepalive" mapstructure:"disable-keepalive"`
|
||||
DisableCompression bool `json:"disable-compression" yaml:"disable-compression" toml:"disable-compression" mapstructure:"disable-compression"`
|
||||
|
||||
MaxIdleConns int `json:"max-idle-conns" yaml:"max-idle-conns" toml:"max-idle-conns" mapstructure:"max-idle-conns"`
|
||||
MaxIdleConnsPerHost int `json:"max-idle-conns-per-host" yaml:"max-idle-conns-per-host" toml:"max-idle-conns-per-host" mapstructure:"max-idle-conns-per-host"`
|
||||
MaxConnsPerHost int `json:"max-conns-per-host" yaml:"max-conns-per-host" toml:"max-conns-per-host" mapstructure:"max-conns-per-host"`
|
||||
|
||||
TimeoutGlobal libdur.Duration `json:"timeout-global,omitempty" yaml:"timeout-global,omitempty" toml:"timeout-global,omitempty" mapstructure:"timeout-global,omitempty"`
|
||||
TimeoutKeepAlive libdur.Duration `json:"timeout-keepalive,omitempty" yaml:"timeout-keepalive" toml:"timeout-keepalive" mapstructure:"timeout-keepalive,omitempty"`
|
||||
TimeoutTLSHandshake libdur.Duration `json:"timeout-tls-handshake,omitempty" yaml:"timeout-tls-handshake,omitempty" toml:"timeout-tls-handshake,omitempty" mapstructure:"timeout-tls-handshake,omitempty"`
|
||||
TimeoutExpectContinue libdur.Duration `json:"timeout-expect-continue,omitempty" yaml:"timeout-expect-continue,omitempty" toml:"timeout-expect-continue,omitempty" mapstructure:"timeout-expect-continue,omitempty"`
|
||||
TimeoutIdleConn libdur.Duration `json:"timeout-idle-conn,omitempty" yaml:"timeout-idle-conn,omitempty" toml:"timeout-idle-conn,omitempty" mapstructure:"timeout-idle-conn,omitempty"`
|
||||
TimeoutResponseHeader libdur.Duration `json:"timeout-response-header,omitempty" yaml:"timeout-response-headern,omitempty" toml:"timeout-response-header,omitempty" mapstructure:"timeout-response-header,omitempty"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
DNSMapper map[string]string `json:"dns-mapper,omitempty" yaml:"dns-mapper,omitempty" toml:"dns-mapper,omitempty" mapstructure:"dns-mapper,omitempty"`
|
||||
TimerClean libdur.Duration `json:"timer-clean,omitempty" yaml:"timer-clean,omitempty" toml:"timer-clean,omitempty" mapstructure:"timer-clean,omitempty"`
|
||||
Transport TransportConfig `json:"transport,omitempty" yaml:"transport,omitempty" toml:"transport,omitempty" mapstructure:"transport,omitempty"`
|
||||
}
|
||||
|
||||
func DefaultConfig(indent string) []byte {
|
||||
var (
|
||||
res = bytes.NewBuffer(make([]byte, 0))
|
||||
def = []byte(`{
|
||||
"dns-mapper": {
|
||||
"localhost":"127.0.0.1"
|
||||
},
|
||||
"timer-clean": "3m",
|
||||
"transport": {
|
||||
"proxy": null,
|
||||
"tls-config": ` + string(cmptls.DefaultConfig(cfgcst.JSONIndent)) + `,
|
||||
"disable-http2": false,
|
||||
"disable-keepalive": false,
|
||||
"disable-compression": false,
|
||||
"max-idle-conns": 50,
|
||||
"max-idle-conns-per-host": 5,
|
||||
"max-conns-per-host": 25,
|
||||
"timeout-global": "30s",
|
||||
"timeout-keepalive": "15s",
|
||||
"timeout-tls-handshake": "10s",
|
||||
"timeout-expect-continue": "3s",
|
||||
"timeout-idle-conn": "30s",
|
||||
"timeout-response-header": "0s"
|
||||
}
|
||||
}`)
|
||||
)
|
||||
if err := json.Indent(res, def, indent, cfgcst.JSONIndent); err != nil {
|
||||
return def
|
||||
} else {
|
||||
return res.Bytes()
|
||||
}
|
||||
}
|
||||
|
||||
func (o Config) Validate() liberr.Error {
|
||||
var e = ErrorValidatorError.Error(nil)
|
||||
|
||||
if err := libval.New().Struct(o); err != nil {
|
||||
if er, ok := err.(*libval.InvalidValidationError); ok {
|
||||
e.Add(er)
|
||||
}
|
||||
|
||||
for _, er := range err.(libval.ValidationErrors) {
|
||||
//nolint #goerr113
|
||||
e.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", er.Namespace(), er.ActualTag()))
|
||||
}
|
||||
}
|
||||
|
||||
if !e.HasParent() {
|
||||
e = nil
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (o Config) New(ctx context.Context, fct libtls.FctRootCA) DNSMapper {
|
||||
return New(ctx, &o, fct)
|
||||
}
|
62
httpcli/dns-mapper/errors.go
Normal file
62
httpcli/dns-mapper/errors.go
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package dns_mapper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgHttpCliDNSMapper
|
||||
ErrorParamInvalid
|
||||
ErrorValidatorError
|
||||
ErrorClientTransportHttp2
|
||||
)
|
||||
|
||||
func init() {
|
||||
if liberr.ExistInMapMessage(ErrorParamEmpty) {
|
||||
panic(fmt.Errorf("error code collision with package golib/httpcli"))
|
||||
}
|
||||
liberr.RegisterIdFctMessage(ErrorParamEmpty, getMessage)
|
||||
}
|
||||
|
||||
func getMessage(code liberr.CodeError) (message string) {
|
||||
switch code {
|
||||
case ErrorParamEmpty:
|
||||
return "at least one given parameters is empty"
|
||||
case ErrorParamInvalid:
|
||||
return "at least one given parameters is invalid"
|
||||
case ErrorValidatorError:
|
||||
return "config seems to be invalid"
|
||||
case ErrorClientTransportHttp2:
|
||||
return "error while configure http2 transport for client"
|
||||
}
|
||||
|
||||
return liberr.NullMessage
|
||||
}
|
91
httpcli/dns-mapper/interface.go
Normal file
91
httpcli/dns-mapper/interface.go
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package dns_mapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libdur "github.com/nabbar/golib/duration"
|
||||
)
|
||||
|
||||
type DNSMapper interface {
|
||||
Add(endpoint, ip string)
|
||||
Get(endpoint string) string
|
||||
Del(endpoint string)
|
||||
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
Transport(cfg TransportConfig) *http.Transport
|
||||
Client(cfg TransportConfig) *http.Client
|
||||
|
||||
DefaultTransport() *http.Transport
|
||||
DefaultClient() *http.Client
|
||||
|
||||
TimeCleaner(ctx context.Context, dur time.Duration)
|
||||
}
|
||||
|
||||
func New(ctx context.Context, cfg *Config, fct libtls.FctRootCA) DNSMapper {
|
||||
if cfg == nil {
|
||||
cfg = &Config{
|
||||
DNSMapper: make(map[string]string),
|
||||
TimerClean: libdur.ParseDuration(3 * time.Minute),
|
||||
Transport: TransportConfig{
|
||||
Proxy: nil,
|
||||
TLSConfig: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if fct == nil {
|
||||
fct = func() []string {
|
||||
return make([]string, 0)
|
||||
}
|
||||
}
|
||||
|
||||
d := &dmp{
|
||||
d: new(sync.Map),
|
||||
z: new(sync.Map),
|
||||
c: new(atomic.Value),
|
||||
t: new(atomic.Value),
|
||||
f: fct,
|
||||
}
|
||||
|
||||
for edp, adr := range cfg.DNSMapper {
|
||||
d.Add(edp, adr)
|
||||
}
|
||||
|
||||
d.c.Store(cfg)
|
||||
_ = d.DefaultTransport()
|
||||
d.TimeCleaner(ctx, cfg.TimerClean.Time())
|
||||
|
||||
return d
|
||||
}
|
209
httpcli/dns-mapper/model.go
Normal file
209
httpcli/dns-mapper/model.go
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package dns_mapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
)
|
||||
|
||||
type dmp struct {
|
||||
d *sync.Map
|
||||
z *sync.Map
|
||||
c *atomic.Value // *Config
|
||||
t *atomic.Value // *http transport
|
||||
f libtls.FctRootCA
|
||||
}
|
||||
|
||||
func (o *dmp) config() *Config {
|
||||
var cfg = &Config{}
|
||||
|
||||
if i := o.c.Load(); i == nil {
|
||||
return cfg
|
||||
} else if c, k := i.(*Config); !k {
|
||||
return cfg
|
||||
} else {
|
||||
*cfg = *c
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) configDialerTimeout() time.Duration {
|
||||
if cfg := o.config(); cfg == nil {
|
||||
return 30 * time.Second
|
||||
} else if cfg.Transport.TimeoutGlobal == 0 {
|
||||
return 30 * time.Second
|
||||
} else {
|
||||
return cfg.Transport.TimeoutGlobal.Time()
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) configDialerKeepAlive() time.Duration {
|
||||
if cfg := o.config(); cfg == nil {
|
||||
return 15 * time.Second
|
||||
} else if cfg.Transport.TimeoutKeepAlive == 0 {
|
||||
return 15 * time.Second
|
||||
} else {
|
||||
return cfg.Transport.TimeoutKeepAlive.Time()
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) CacheHas(endpoint string) bool {
|
||||
_, l := o.z.Load(endpoint)
|
||||
return l
|
||||
}
|
||||
|
||||
func (o *dmp) CacheGet(endpoint string) string {
|
||||
if i, l := o.z.Load(endpoint); !l {
|
||||
return ""
|
||||
} else if v, k := i.(string); !k {
|
||||
return ""
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) CacheSet(endpoint, ip string) {
|
||||
o.z.Store(endpoint, ip)
|
||||
}
|
||||
|
||||
func (o *dmp) Add(endpoint, ip string) {
|
||||
o.d.Store(endpoint, ip)
|
||||
}
|
||||
|
||||
func (o *dmp) Get(endpoint string) string {
|
||||
if i, l := o.d.Load(endpoint); !l {
|
||||
return ""
|
||||
} else if s, k := i.(string); !k {
|
||||
return ""
|
||||
} else {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) Search(endpoint string) string {
|
||||
var res string
|
||||
|
||||
o.d.Range(func(key, value any) bool {
|
||||
var (
|
||||
e error
|
||||
k bool
|
||||
h string
|
||||
|
||||
src string
|
||||
dst string
|
||||
)
|
||||
|
||||
if src, k = key.(string); !k {
|
||||
return true
|
||||
} else if dst, k = value.(string); !k {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.EqualFold(src, endpoint) {
|
||||
res = dst
|
||||
return false
|
||||
}
|
||||
|
||||
h, _, e = net.SplitHostPort(src)
|
||||
if e == nil {
|
||||
src = h
|
||||
}
|
||||
|
||||
if strings.EqualFold(src, endpoint) {
|
||||
res = dst
|
||||
return false
|
||||
} else if strings.HasPrefix(src, "*.") {
|
||||
// search for wildcard
|
||||
f := src
|
||||
t := endpoint
|
||||
|
||||
for strings.HasPrefix(f, "*.") {
|
||||
if p := strings.SplitAfterN(f, ".", 2); len(p) > 1 {
|
||||
f = p[1]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
if p := strings.SplitAfterN(t, ".", 2); len(p) > 1 {
|
||||
t = p[1]
|
||||
}
|
||||
}
|
||||
|
||||
if strings.EqualFold(f, t) {
|
||||
res = dst
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (o *dmp) Del(endpoint string) {
|
||||
o.d.Delete(endpoint)
|
||||
}
|
||||
|
||||
func (o *dmp) TimeCleaner(ctx context.Context, dur time.Duration) {
|
||||
if dur < 5*time.Second {
|
||||
dur = 5 * time.Minute
|
||||
}
|
||||
|
||||
go func() {
|
||||
var tck = time.NewTicker(dur)
|
||||
defer tck.Stop()
|
||||
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-tck.C:
|
||||
o.DefaultTransport().CloseIdleConnections()
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (o *dmp) Len() int {
|
||||
var i int
|
||||
o.d.Range(func(key, value any) bool {
|
||||
i++
|
||||
return true
|
||||
})
|
||||
return i
|
||||
}
|
199
httpcli/dns-mapper/transport.go
Normal file
199
httpcli/dns-mapper/transport.go
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Nicolas JUHEL
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package dns_mapper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libdur "github.com/nabbar/golib/duration"
|
||||
)
|
||||
|
||||
func (o *dmp) dialer() *net.Dialer {
|
||||
return &net.Dialer{
|
||||
Timeout: o.configDialerTimeout(),
|
||||
DualStack: true,
|
||||
KeepAlive: o.configDialerKeepAlive(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) Dial(network, address string) (net.Conn, error) {
|
||||
return o.DialContext(context.Background(), network, address)
|
||||
}
|
||||
|
||||
func (o *dmp) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
var (
|
||||
e error
|
||||
d = o.dialer()
|
||||
a string
|
||||
|
||||
hs string
|
||||
ps string
|
||||
)
|
||||
|
||||
if o.CacheHas(address) {
|
||||
a = o.CacheGet(address)
|
||||
}
|
||||
|
||||
if len(a) > 0 {
|
||||
return d.DialContext(ctx, network, a)
|
||||
} else {
|
||||
a = o.Get(address)
|
||||
}
|
||||
|
||||
hs, ps, e = net.SplitHostPort(address)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
if len(a) < 1 {
|
||||
a = o.Get(hs)
|
||||
}
|
||||
|
||||
if len(a) < 1 {
|
||||
a = o.Search(hs)
|
||||
}
|
||||
|
||||
if len(a) < 1 {
|
||||
o.CacheSet(address, address)
|
||||
return d.DialContext(ctx, network, address)
|
||||
} else if _, _, e = net.SplitHostPort(a); e == nil {
|
||||
o.CacheSet(address, a)
|
||||
return d.DialContext(ctx, network, a)
|
||||
} else {
|
||||
a = net.JoinHostPort(a, ps)
|
||||
o.CacheSet(address, a)
|
||||
return d.DialContext(ctx, network, a)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) Transport(cfg TransportConfig) *http.Transport {
|
||||
var prx func(*http.Request) (*url.URL, error)
|
||||
if cfg.Proxy == nil {
|
||||
prx = http.ProxyFromEnvironment
|
||||
} else {
|
||||
prx = http.ProxyURL(cfg.Proxy)
|
||||
}
|
||||
|
||||
var (
|
||||
err error
|
||||
ssl libtls.TLSConfig
|
||||
)
|
||||
|
||||
if cfg.TLSConfig == nil {
|
||||
ssl = libtls.New()
|
||||
ssl.SetVersionMin(tls.VersionTLS12)
|
||||
ssl.SetVersionMax(tls.VersionTLS13)
|
||||
} else if ssl, err = cfg.TLSConfig.New(); err != nil {
|
||||
ssl = libtls.New()
|
||||
ssl.SetVersionMin(tls.VersionTLS12)
|
||||
ssl.SetVersionMax(tls.VersionTLS13)
|
||||
}
|
||||
|
||||
for _, c := range o.f() {
|
||||
ssl.AddRootCAString(c)
|
||||
}
|
||||
|
||||
if cfg.TimeoutGlobal == 0 {
|
||||
cfg.TimeoutGlobal = libdur.ParseDuration(30 * time.Second)
|
||||
}
|
||||
|
||||
if cfg.TimeoutKeepAlive == 0 {
|
||||
cfg.TimeoutKeepAlive = libdur.ParseDuration(15 * time.Second)
|
||||
}
|
||||
|
||||
if cfg.TimeoutTLSHandshake == 0 {
|
||||
cfg.TimeoutTLSHandshake = libdur.ParseDuration(10 * time.Second)
|
||||
}
|
||||
|
||||
if cfg.TimeoutExpectContinue == 0 {
|
||||
cfg.TimeoutExpectContinue = libdur.ParseDuration(3 * time.Second)
|
||||
}
|
||||
|
||||
if cfg.TimeoutIdleConn == 0 {
|
||||
cfg.TimeoutIdleConn = libdur.ParseDuration(90 * time.Second)
|
||||
}
|
||||
|
||||
if cfg.MaxConnsPerHost == 0 {
|
||||
cfg.MaxIdleConns = 25
|
||||
}
|
||||
|
||||
if cfg.MaxIdleConnsPerHost == 0 {
|
||||
cfg.MaxIdleConnsPerHost = 5
|
||||
}
|
||||
|
||||
if cfg.MaxIdleConns == 0 {
|
||||
cfg.MaxIdleConns = 25
|
||||
}
|
||||
|
||||
return &http.Transport{
|
||||
Proxy: prx,
|
||||
Dial: o.Dial,
|
||||
DialContext: o.DialContext,
|
||||
TLSClientConfig: ssl.TlsConfig(""),
|
||||
TLSHandshakeTimeout: cfg.TimeoutTLSHandshake.Time(),
|
||||
DisableKeepAlives: cfg.DisableKeepAlive,
|
||||
DisableCompression: cfg.DisableCompression,
|
||||
MaxIdleConns: cfg.MaxIdleConns,
|
||||
MaxIdleConnsPerHost: cfg.MaxIdleConnsPerHost,
|
||||
MaxConnsPerHost: cfg.MaxConnsPerHost,
|
||||
IdleConnTimeout: cfg.TimeoutIdleConn.Time(),
|
||||
ResponseHeaderTimeout: cfg.TimeoutResponseHeader.Time(),
|
||||
ExpectContinueTimeout: cfg.TimeoutExpectContinue.Time(),
|
||||
ForceAttemptHTTP2: !cfg.DisableHTTP2,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) Client(cfg TransportConfig) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: o.Transport(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dmp) DefaultTransport() *http.Transport {
|
||||
i := o.t.Load()
|
||||
if i != nil {
|
||||
if t, k := i.(*http.Transport); k {
|
||||
return t
|
||||
}
|
||||
}
|
||||
|
||||
t := o.Transport(o.config().Transport)
|
||||
o.t.Store(t)
|
||||
return t
|
||||
}
|
||||
|
||||
func (o *dmp) DefaultClient() *http.Client {
|
||||
return &http.Client{
|
||||
Transport: o.DefaultTransport(),
|
||||
}
|
||||
}
|
@@ -47,10 +47,19 @@ var srv = &http.Server{
|
||||
Handler: Hello(),
|
||||
}
|
||||
|
||||
var (
|
||||
ctx context.Context
|
||||
cnl context.CancelFunc
|
||||
)
|
||||
|
||||
func TestGolibHttpCliHelper(t *testing.T) {
|
||||
defer func() {
|
||||
_ = srv.Shutdown(context.Background())
|
||||
}()
|
||||
|
||||
ctx, cnl = context.WithCancel(context.Background())
|
||||
defer cnl()
|
||||
|
||||
go func() {
|
||||
if e := srv.ListenAndServe(); e != nil {
|
||||
if !errors.Is(e, http.ErrServerClosed) {
|
||||
@@ -58,6 +67,7 @@ func TestGolibHttpCliHelper(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
RegisterFailHandler(Fail)
|
||||
|
@@ -28,11 +28,11 @@ package httpcli_test
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libdur "github.com/nabbar/golib/duration"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
"github.com/nabbar/golib/httpcli"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -40,7 +40,8 @@ import (
|
||||
var (
|
||||
cli *http.Client
|
||||
err error
|
||||
opt httpcli.Options
|
||||
opt htcdns.Config
|
||||
dns htcdns.DNSMapper
|
||||
rsp *http.Response
|
||||
)
|
||||
|
||||
@@ -52,24 +53,29 @@ var _ = Describe("HttpCli", func() {
|
||||
}()
|
||||
Context("Get URL with a Force IP", func() {
|
||||
It("Create new client must succeed", func() {
|
||||
opt = httpcli.Options{
|
||||
Timeout: 0,
|
||||
Http2: true,
|
||||
TLS: httpcli.OptionTLS{
|
||||
Enable: false,
|
||||
Config: libtls.Config{},
|
||||
},
|
||||
ForceIP: httpcli.OptionForceIP{
|
||||
Enable: true,
|
||||
Net: libptc.NetworkTCP,
|
||||
IP: "127.0.0.1:8080",
|
||||
},
|
||||
opt = htcdns.Config{
|
||||
DNSMapper: make(map[string]string),
|
||||
TimerClean: libdur.ParseDuration(30 * time.Second),
|
||||
Transport: htcdns.TransportConfig{},
|
||||
}
|
||||
cli, err = opt.GetClient(nil, "")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
dns = htcdns.New(ctx, &opt, nil)
|
||||
|
||||
cli = dns.DefaultClient()
|
||||
Expect(cli).ToNot(BeNil())
|
||||
})
|
||||
It("Get URL must succeed", func() {
|
||||
It("Get URL must succeed for DNS Mapper with host", func() {
|
||||
dns.Del("test.me.example.com:80")
|
||||
dns.Add("test.me.example.com", "127.0.0.1:8080")
|
||||
|
||||
rsp, err = cli.Get("http://test.me.example.com/path/any/thing")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(rsp).ToNot(BeNil())
|
||||
})
|
||||
It("Get URL must succeed for DNS Mapper with host & port", func() {
|
||||
dns.Del("test.me.example.com")
|
||||
dns.Add("test.me.example.com:80", "127.0.0.1:8080")
|
||||
|
||||
rsp, err = cli.Get("http://test.me.example.com/path/any/thing")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(rsp).ToNot(BeNil())
|
||||
|
@@ -27,8 +27,6 @@
|
||||
package httpcli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -36,9 +34,8 @@ import (
|
||||
|
||||
libval "github.com/go-playground/validator/v10"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
cmptls "github.com/nabbar/golib/config/components/tls"
|
||||
cfgcst "github.com/nabbar/golib/config/const"
|
||||
liberr "github.com/nabbar/golib/errors"
|
||||
htcdns "github.com/nabbar/golib/httpcli/dns-mapper"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
)
|
||||
|
||||
@@ -72,33 +69,7 @@ type Options struct {
|
||||
}
|
||||
|
||||
func DefaultConfig(indent string) []byte {
|
||||
var (
|
||||
res = bytes.NewBuffer(make([]byte, 0))
|
||||
def = []byte(`{
|
||||
"timeout":"0s",
|
||||
"disable-keep-alive": false,
|
||||
"disable-compression": false,
|
||||
"http2": true,
|
||||
"tls": ` + string(cmptls.DefaultConfig(cfgcst.JSONIndent)) + `,
|
||||
"force_ip": {
|
||||
"enable": false,
|
||||
"net":"tcp",
|
||||
"ip":"127.0.0.1:8080",
|
||||
"local":"127.0.0.1"
|
||||
},
|
||||
"proxy": {
|
||||
"enable": false,
|
||||
"endpoint":"http://example.com",
|
||||
"username":"example",
|
||||
"password":"example"
|
||||
}
|
||||
}`)
|
||||
)
|
||||
if err := json.Indent(res, def, indent, cfgcst.JSONIndent); err != nil {
|
||||
return def
|
||||
} else {
|
||||
return res.Bytes()
|
||||
}
|
||||
return htcdns.DefaultConfig(indent)
|
||||
}
|
||||
|
||||
func (o Options) Validate() liberr.Error {
|
||||
@@ -123,60 +94,5 @@ func (o Options) Validate() liberr.Error {
|
||||
}
|
||||
|
||||
func (o Options) GetClient(def libtls.TLSConfig, servername string) (*http.Client, liberr.Error) {
|
||||
var (
|
||||
tls libtls.TLSConfig
|
||||
edp *url.URL
|
||||
)
|
||||
|
||||
if t, e := o._GetTLS(def); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
tls = t
|
||||
}
|
||||
|
||||
if o.Proxy.Enable && o.Proxy.Endpoint != nil {
|
||||
edp = &url.URL{
|
||||
Scheme: o.Proxy.Endpoint.Scheme,
|
||||
Opaque: o.Proxy.Endpoint.Opaque,
|
||||
User: nil,
|
||||
Host: o.Proxy.Endpoint.Host,
|
||||
Path: o.Proxy.Endpoint.Path,
|
||||
RawPath: o.Proxy.Endpoint.RawPath,
|
||||
OmitHost: o.Proxy.Endpoint.OmitHost,
|
||||
ForceQuery: o.Proxy.Endpoint.ForceQuery,
|
||||
RawQuery: o.Proxy.Endpoint.RawQuery,
|
||||
Fragment: o.Proxy.Endpoint.Fragment,
|
||||
RawFragment: o.Proxy.Endpoint.RawFragment,
|
||||
}
|
||||
|
||||
if len(o.Proxy.Password) > 0 {
|
||||
edp.User = url.UserPassword(o.Proxy.Username, o.Proxy.Password)
|
||||
} else if len(o.Proxy.Username) > 0 {
|
||||
edp.User = url.User(o.Proxy.Username)
|
||||
} else if o.Proxy.Endpoint.User != nil {
|
||||
if p, k := o.Proxy.Endpoint.User.Password(); k {
|
||||
edp.User = url.UserPassword(o.Proxy.Endpoint.User.Username(), p)
|
||||
} else {
|
||||
edp.User = url.User(o.Proxy.Endpoint.User.Username())
|
||||
}
|
||||
}
|
||||
|
||||
if edp != nil && len(edp.String()) < 1 {
|
||||
edp = nil
|
||||
}
|
||||
}
|
||||
|
||||
var tr *http.Transport
|
||||
|
||||
tr = GetTransport(tls.TlsConfig(""), edp, o.DisableKeepAlive, o.DisableCompression, o.Http2)
|
||||
SetTransportDial(tr, o.ForceIP.Enable, o.ForceIP.Net, o.ForceIP.IP, o.ForceIP.Local)
|
||||
return GetClient(tr, o.Http2, o.Timeout)
|
||||
}
|
||||
|
||||
func (o Options) _GetTLS(def libtls.TLSConfig) (libtls.TLSConfig, liberr.Error) {
|
||||
if o.TLS.Enable {
|
||||
return o.TLS.Config.NewFrom(def)
|
||||
} else {
|
||||
return libtls.Default.Clone(), nil
|
||||
}
|
||||
return GetClient(), nil
|
||||
}
|
||||
|
@@ -29,10 +29,9 @@ package httpserver
|
||||
import (
|
||||
"sync"
|
||||
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
srvtps "github.com/nabbar/golib/httpserver/types"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libsrv "github.com/nabbar/golib/server"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
|
@@ -30,14 +30,15 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
logent "github.com/nabbar/golib/logger/entry"
|
||||
loglvl "github.com/nabbar/golib/logger/level"
|
||||
|
||||
libmon "github.com/nabbar/golib/monitor"
|
||||
moninf "github.com/nabbar/golib/monitor/info"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
)
|
||||
|
||||
@@ -90,9 +91,16 @@ func (o *srv) runAndHealthy(ctx context.Context) error {
|
||||
return errNotRunning
|
||||
} else if e := o.PortNotUse(ctx, o.GetBindable()); e != nil {
|
||||
return e
|
||||
} else {
|
||||
d := &net.Dialer{}
|
||||
co, ce := d.DialContext(ctx, libptc.NetworkTCP.Code(), o.GetBindable())
|
||||
defer func() {
|
||||
if co != nil {
|
||||
_ = co.Close()
|
||||
}
|
||||
}()
|
||||
return ce
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *srv) MonitorName() string {
|
||||
|
@@ -28,6 +28,7 @@ package pool
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
libhtp "github.com/nabbar/golib/httpserver"
|
||||
)
|
||||
@@ -106,3 +107,17 @@ func (o *pool) IsRunning() bool {
|
||||
|
||||
return run
|
||||
}
|
||||
|
||||
func (o *pool) Uptime() time.Duration {
|
||||
var res time.Duration
|
||||
|
||||
o.Walk(func(name string, val libhtp.Server) bool {
|
||||
if dur := val.Uptime(); res < dur {
|
||||
res = dur
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return res
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
srvtps "github.com/nabbar/golib/httpserver/types"
|
||||
loglvl "github.com/nabbar/golib/logger/level"
|
||||
@@ -227,3 +228,14 @@ func (o *srv) runFuncStop(ctx context.Context) (err error) {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (o *srv) Uptime() time.Duration {
|
||||
o.m.RLock()
|
||||
defer o.m.RUnlock()
|
||||
|
||||
if o.r != nil {
|
||||
return o.r.Uptime()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
)
|
||||
@@ -98,3 +99,18 @@ func (o *pool) IsRunning() bool {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (o *pool) Uptime() time.Duration {
|
||||
var res time.Duration
|
||||
|
||||
o.MonitorWalk(func(name string, val montps.Monitor) bool {
|
||||
if dur := val.Uptime(); res < dur {
|
||||
res = dur
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return res
|
||||
|
||||
}
|
||||
|
@@ -33,13 +33,12 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
libver "github.com/nabbar/golib/version"
|
||||
)
|
||||
|
||||
@@ -105,7 +104,7 @@ type Request interface {
|
||||
|
||||
GetOption() *Options
|
||||
SetOption(opt *Options) error
|
||||
RegisterHTTPClient(fct libtls.FctHttpClient)
|
||||
RegisterHTTPClient(cli libhtc.HttpClient)
|
||||
RegisterDefaultLogger(fct liblog.FuncLog)
|
||||
RegisterContext(fct libctx.FuncContext)
|
||||
|
||||
@@ -120,20 +119,23 @@ type Request interface {
|
||||
HealthCheck(ctx context.Context) error
|
||||
}
|
||||
|
||||
func New(ctx libctx.FuncContext, opt *Options) (Request, error) {
|
||||
func New(ctx libctx.FuncContext, opt *Options, cli libhtc.HttpClient) (Request, error) {
|
||||
r := &request{
|
||||
s: sync.Mutex{},
|
||||
o: nil,
|
||||
x: ctx,
|
||||
f: nil,
|
||||
l: nil,
|
||||
u: nil,
|
||||
h: make(url.Values),
|
||||
p: make(url.Values),
|
||||
b: bytes.NewBuffer(make([]byte, 0)),
|
||||
m: http.MethodGet,
|
||||
e: nil,
|
||||
c: new(atomic.Value),
|
||||
}
|
||||
|
||||
r.c.Store(cli)
|
||||
|
||||
if e := r.SetOption(opt); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
|
@@ -29,15 +29,13 @@ package request
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -51,16 +49,16 @@ const (
|
||||
type request struct {
|
||||
s sync.Mutex
|
||||
|
||||
o *atomic.Value // Options
|
||||
x libctx.FuncContext // Context function
|
||||
f libtls.FctHttpClient // Http client func
|
||||
l liblog.FuncLog // Default logger
|
||||
u *url.URL // endpoint url
|
||||
h url.Values // header values
|
||||
p url.Values // parameters values
|
||||
b io.Reader // body io reader
|
||||
m string // method
|
||||
e *requestError // Error pointer
|
||||
o *atomic.Value // Options
|
||||
x libctx.FuncContext // Context function
|
||||
l liblog.FuncLog // Default logger
|
||||
u *url.URL // endpoint url
|
||||
h url.Values // header values
|
||||
p url.Values // parameters values
|
||||
b io.Reader // body io reader
|
||||
m string // method
|
||||
e *requestError // Error pointer
|
||||
c *atomic.Value // libhtc HTTPClient
|
||||
}
|
||||
|
||||
func (r *request) Clone() (Request, error) {
|
||||
@@ -97,7 +95,7 @@ func (r *request) New() (Request, error) {
|
||||
c = &Options{}
|
||||
}
|
||||
|
||||
if i, e := New(r.x, c); e != nil {
|
||||
if i, e := New(r.x, c, r.client()); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
n = i.(*request)
|
||||
@@ -122,10 +120,6 @@ func (r *request) New() (Request, error) {
|
||||
n.l = r.l
|
||||
}
|
||||
|
||||
if r.f != nil {
|
||||
n.f = r.f
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -139,28 +133,16 @@ func (r *request) context() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func (r *request) client() *http.Client {
|
||||
var h string
|
||||
|
||||
if r.u != nil {
|
||||
h = r.u.Hostname()
|
||||
func (r *request) client() libhtc.HttpClient {
|
||||
if i := r.c.Load(); i != nil {
|
||||
if c, k := i.(libhtc.HttpClient); k {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
if r.f == nil {
|
||||
return r.clientDefault(h)
|
||||
} else if c := r.f(r.defaultTLS(), h); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return r.clientDefault(h)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *request) clientDefault(h string) *http.Client {
|
||||
if cfg := r.options(); cfg != nil {
|
||||
return cfg.ClientHTTP(h)
|
||||
} else {
|
||||
return &http.Client{}
|
||||
}
|
||||
c := libhtc.GetClient()
|
||||
r.c.Store(c)
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *request) Error() Error {
|
||||
|
@@ -36,9 +36,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
logent "github.com/nabbar/golib/logger/entry"
|
||||
|
||||
loglvl "github.com/nabbar/golib/logger/level"
|
||||
|
||||
libmon "github.com/nabbar/golib/monitor"
|
||||
moninf "github.com/nabbar/golib/monitor/info"
|
||||
montps "github.com/nabbar/golib/monitor/types"
|
||||
|
@@ -28,17 +28,14 @@ package request
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
|
||||
moncfg "github.com/nabbar/golib/monitor/types"
|
||||
|
||||
libval "github.com/go-playground/validator/v10"
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libctx "github.com/nabbar/golib/context"
|
||||
libhtc "github.com/nabbar/golib/httpcli"
|
||||
liblog "github.com/nabbar/golib/logger"
|
||||
moncfg "github.com/nabbar/golib/monitor/types"
|
||||
)
|
||||
|
||||
type OptionsCredentials struct {
|
||||
@@ -73,10 +70,9 @@ type OptionsHealthResult struct {
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
Endpoint string `json:"endpoint" yaml:"endpoint" toml:"endpoint" mapstructure:"endpoint" validate:"url"`
|
||||
HttpClient libhtc.Options `json:"http_client" yaml:"http_client" toml:"http_client" mapstructure:"http_client" validate:""`
|
||||
Auth OptionsAuth `json:"auth" yaml:"auth" toml:"auth" mapstructure:"auth" validate:""`
|
||||
Health OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
Endpoint string `json:"endpoint" yaml:"endpoint" toml:"endpoint" mapstructure:"endpoint" validate:"url"`
|
||||
Auth OptionsAuth `json:"auth" yaml:"auth" toml:"auth" mapstructure:"auth" validate:""`
|
||||
Health OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
|
||||
|
||||
tls libtls.FctTLSDefault
|
||||
log liblog.FuncLog
|
||||
@@ -140,20 +136,8 @@ func (o *Options) SetDefaultLog(fct liblog.FuncLog) {
|
||||
o.log = fct
|
||||
}
|
||||
|
||||
func (o *Options) ClientHTTPTLS(tls libtls.TLSConfig, servername string) *http.Client {
|
||||
if c, e := o.HttpClient.GetClient(tls, servername); e == nil {
|
||||
return c
|
||||
}
|
||||
|
||||
return &http.Client{}
|
||||
}
|
||||
|
||||
func (o *Options) ClientHTTP(servername string) *http.Client {
|
||||
return o.ClientHTTPTLS(o.defaultTLS(), servername)
|
||||
}
|
||||
|
||||
func (o *Options) New(ctx libctx.FuncContext) (Request, error) {
|
||||
if n, e := New(ctx, o); e != nil {
|
||||
func (o *Options) New(ctx libctx.FuncContext, cli libhtc.HttpClient) (Request, error) {
|
||||
if n, e := New(ctx, o, cli); e != nil {
|
||||
return nil, e
|
||||
} else {
|
||||
if o.log != nil {
|
||||
@@ -166,7 +150,6 @@ func (o *Options) New(ctx libctx.FuncContext) (Request, error) {
|
||||
return l
|
||||
})
|
||||
}
|
||||
n.RegisterHTTPClient(o.ClientHTTPTLS)
|
||||
return n, nil
|
||||
}
|
||||
}
|
||||
@@ -200,8 +183,6 @@ func (o *Options) Update(ctx libctx.FuncContext, req Request) (Request, error) {
|
||||
})
|
||||
}
|
||||
|
||||
n.RegisterHTTPClient(o.ClientHTTPTLS)
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -245,11 +226,11 @@ func (r *request) SetOption(opt *Options) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) RegisterHTTPClient(fct libtls.FctHttpClient) {
|
||||
r.s.Lock()
|
||||
defer r.s.Unlock()
|
||||
|
||||
r.f = fct
|
||||
func (r *request) RegisterHTTPClient(cli libhtc.HttpClient) {
|
||||
if cli == nil {
|
||||
return
|
||||
}
|
||||
r.c.Store(cli)
|
||||
}
|
||||
|
||||
func (r *request) RegisterDefaultLogger(fct liblog.FuncLog) {
|
||||
|
@@ -53,7 +53,7 @@ func (o *sem) defOpts(unit interface{}, name, job string, bar semtps.Bar) []sdkm
|
||||
|
||||
if len(name) > 0 {
|
||||
dec = append(dec,
|
||||
mpbdec.Name(name, mpbdec.WC{W: len(name) + 1, C: mpbdec.DidentRight}),
|
||||
mpbdec.Name(name, mpbdec.WC{W: len(name) + 1, C: mpbdec.DindentRight}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (o *sem) defOpts(unit interface{}, name, job string, bar semtps.Bar) []sdkm
|
||||
)
|
||||
}
|
||||
dec = append(dec,
|
||||
mpbdec.Name(job, mpbdec.WC{W: len(job) + 1, C: mpbdec.DidentRight | mpbdec.DextraSpace}),
|
||||
mpbdec.Name(job, mpbdec.WC{W: len(job) + 1, C: mpbdec.DindentRight | mpbdec.DextraSpace}),
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Action func(ctx context.Context) error
|
||||
@@ -44,6 +45,9 @@ type Server interface {
|
||||
|
||||
// IsRunning return true if the server is currently running
|
||||
IsRunning() bool
|
||||
|
||||
//Uptime return the duration since last launch
|
||||
Uptime() time.Duration
|
||||
}
|
||||
|
||||
type WaitNotify interface {
|
||||
|
@@ -44,6 +44,7 @@ func New(start, stop func(ctx context.Context) error) StartStop {
|
||||
e: new(atomic.Value),
|
||||
f: start,
|
||||
s: stop,
|
||||
t: new(atomic.Value),
|
||||
c: new(atomic.Value),
|
||||
}
|
||||
}
|
||||
|
@@ -52,6 +52,7 @@ type run struct {
|
||||
e *atomic.Value // slice []error
|
||||
f libsrv.Action
|
||||
s libsrv.Action
|
||||
t *atomic.Value
|
||||
c *atomic.Value // chan struct{}
|
||||
}
|
||||
|
||||
@@ -96,6 +97,8 @@ func (o *run) Stop(ctx context.Context) error {
|
||||
t = time.NewTicker(pollStop)
|
||||
)
|
||||
|
||||
o.t.Store(time.Time{})
|
||||
|
||||
defer func() {
|
||||
if rec := recover(); rec != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "recovering panic thread on Stop function in gollib/server/startStop/model.\n%v\n", rec)
|
||||
@@ -133,6 +136,7 @@ func (o *run) Start(ctx context.Context) error {
|
||||
|
||||
var can context.CancelFunc
|
||||
ctx, can = context.WithCancel(ctx)
|
||||
o.t.Store(time.Now())
|
||||
|
||||
go func(x context.Context, n context.CancelFunc) {
|
||||
defer n()
|
||||
@@ -191,3 +195,13 @@ func (o *run) checkMeStart(ctx context.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *run) Uptime() time.Duration {
|
||||
if i := o.t.Load(); i == nil {
|
||||
return 0
|
||||
} else if t, k := i.(time.Time); !k {
|
||||
return 0
|
||||
} else {
|
||||
return time.Since(t)
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@ func New(tick time.Duration, fct func(ctx context.Context, tck *time.Ticker) err
|
||||
e: new(atomic.Value),
|
||||
f: fct,
|
||||
d: tick,
|
||||
t: new(atomic.Value),
|
||||
c: new(atomic.Value),
|
||||
}
|
||||
}
|
||||
|
@@ -51,6 +51,7 @@ type run struct {
|
||||
e *atomic.Value // slice []error
|
||||
f func(ctx context.Context, tck *time.Ticker) error
|
||||
d time.Duration
|
||||
t *atomic.Value
|
||||
c *atomic.Value // chan struct{}
|
||||
}
|
||||
|
||||
@@ -78,7 +79,11 @@ func (o *run) Restart(ctx context.Context) error {
|
||||
func (o *run) Stop(ctx context.Context) error {
|
||||
if e := o.checkMe(); e != nil {
|
||||
return e
|
||||
} else if !o.IsRunning() {
|
||||
}
|
||||
|
||||
o.t.Store(time.Time{})
|
||||
|
||||
if !o.IsRunning() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -123,6 +128,8 @@ func (o *run) Start(ctx context.Context) error {
|
||||
o.chanClose()
|
||||
}()
|
||||
|
||||
o.t.Store(time.Now())
|
||||
|
||||
o.chanInit()
|
||||
o.errorsClean()
|
||||
|
||||
@@ -172,3 +179,13 @@ func (o *run) checkMeStart(ctx context.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *run) Uptime() time.Duration {
|
||||
if i := o.t.Load(); i == nil {
|
||||
return 0
|
||||
} else if t, k := i.(time.Time); !k {
|
||||
return 0
|
||||
} else {
|
||||
return time.Since(t)
|
||||
}
|
||||
}
|
||||
|
@@ -31,9 +31,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libsiz "github.com/nabbar/golib/size"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -30,10 +30,8 @@ import (
|
||||
"net"
|
||||
"sync/atomic"
|
||||
|
||||
libsiz "github.com/nabbar/golib/size"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libsiz "github.com/nabbar/golib/size"
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -33,7 +33,6 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
libsiz "github.com/nabbar/golib/size"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -171,7 +171,9 @@ func (o *cli) sendRequest(con net.Conn, r io.Reader) {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
o.fctError(err)
|
||||
}
|
||||
return
|
||||
if len(buf) < 1 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
o.fctInfo(con.LocalAddr(), con.RemoteAddr(), libsck.ConnectionWrite)
|
||||
|
@@ -33,7 +33,6 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
libsiz "github.com/nabbar/golib/size"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -139,7 +139,7 @@ func (o *srv) Listen(ctx context.Context) error {
|
||||
|
||||
if co, ce := l.Accept(); ce != nil && !s.Load() {
|
||||
o.fctError(ce)
|
||||
} else {
|
||||
} else if co != nil {
|
||||
o.fctInfo(co.LocalAddr(), co.RemoteAddr(), libsck.ConnectionNew)
|
||||
go o.Conn(co)
|
||||
}
|
||||
@@ -171,7 +171,9 @@ func (o *srv) Conn(conn net.Conn) {
|
||||
if err != io.EOF {
|
||||
o.fctError(err)
|
||||
}
|
||||
break
|
||||
if len(msg) < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var buf = bytes.NewBuffer(msg)
|
||||
|
@@ -34,9 +34,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -162,7 +162,9 @@ func (o *srv) Listen(ctx context.Context) error {
|
||||
if !stp.Load() {
|
||||
o.fctError(rer)
|
||||
}
|
||||
continue
|
||||
if nbr < 1 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
go func(la, ra net.Addr, b []byte) {
|
||||
|
@@ -33,9 +33,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -44,7 +44,6 @@ import (
|
||||
"syscall"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
@@ -220,7 +219,7 @@ func (o *srv) Listen(ctx context.Context) error {
|
||||
|
||||
if co, ce := l.Accept(); ce != nil && !s.Load() {
|
||||
o.fctError(ce)
|
||||
} else {
|
||||
} else if co != nil {
|
||||
o.fctInfo(co.LocalAddr(), co.RemoteAddr(), libsck.ConnectionNew)
|
||||
go o.Conn(co)
|
||||
}
|
||||
@@ -252,7 +251,9 @@ func (o *srv) Conn(con net.Conn) {
|
||||
if err != io.EOF {
|
||||
o.fctError(err)
|
||||
}
|
||||
break
|
||||
if len(msg) < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var buf = bytes.NewBuffer(msg)
|
||||
|
@@ -37,9 +37,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
@@ -43,7 +43,6 @@ import (
|
||||
"syscall"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
@@ -232,7 +231,9 @@ func (o *srv) Listen(ctx context.Context) error {
|
||||
if !stp.Load() {
|
||||
o.fctError(rer)
|
||||
}
|
||||
continue
|
||||
if nbr < 1 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
go func(la, ra net.Addr, b []byte) {
|
||||
|
@@ -37,9 +37,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
|
||||
libtls "github.com/nabbar/golib/certificates"
|
||||
libptc "github.com/nabbar/golib/network/protocol"
|
||||
libsck "github.com/nabbar/golib/socket"
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user