From 9ba6df7fc08d3dc002037a3cae5bb50261c17aff Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Wed, 20 Oct 2021 17:07:44 +0300 Subject: [PATCH] Make ClientOpts of type struct in httpcfg --- config/config.go | 10 +- config/config_defaults.go | 2 +- config/config_it_test.go | 2 +- config/config_json_test.go | 2 +- config/config_test.go | 4 +- config/httpcfg.go | 214 +++++++++++++++++++++++++-- config/httpcfg_test.go | 10 +- data/conf/cgrates/cgrates.json | 2 +- engine/globalvars.go | 125 +--------------- engine/globalvars_test.go | 4 +- general_tests/all_cfg_rld_it_test.go | 2 +- services/globalvars.go | 18 +-- services/globalvars_it_test.go | 7 - utils/consts.go | 2 +- 14 files changed, 227 insertions(+), 177 deletions(-) diff --git a/config/config.go b/config/config.go index c005913b0..294cd2b6c 100644 --- a/config/config.go +++ b/config/config.go @@ -104,10 +104,12 @@ func newCGRConfig(config []byte) (cfg *CGRConfig, err error) { Items: make(map[string]*ItemOpt), Opts: &StorDBOpts{}, }, - tlsCfg: new(TLSCfg), - cacheCfg: &CacheCfg{Partitions: make(map[string]*CacheParamCfg)}, - listenCfg: new(ListenCfg), - httpCfg: &HTTPCfg{ClientOpts: make(map[string]interface{})}, + tlsCfg: new(TLSCfg), + cacheCfg: &CacheCfg{Partitions: make(map[string]*CacheParamCfg)}, + listenCfg: new(ListenCfg), + httpCfg: &HTTPCfg{ + ClientOpts: &HTTPClientOpts{}, + }, filterSCfg: new(FilterSCfg), cdrsCfg: &CdrsCfg{Opts: &CdrsOpts{ Accounts: []*utils.DynamicBoolOpt{}, diff --git a/config/config_defaults.go b/config/config_defaults.go index 96aa11b2c..8cd21cf53 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -197,7 +197,7 @@ const CGRATES_CFG_JSON = ` "use_basic_auth": false, // use basic authentication "auth_users": {}, // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) "client_opts":{ - "skipTlsVerify": false, // if enabled Http Client will accept any TLS certificate + "skipTLSVerification": false, // if enabled Http Client will accept any TLS certificate // the options to configure the http.Transport "tlsHandshakeTimeout": "10s", "disableKeepAlives": false, diff --git a/config/config_it_test.go b/config/config_it_test.go index 5cfc50e3a..647858997 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -919,7 +919,7 @@ func testCGRConfigReloadConfigFromStringSessionS(t *testing.T) { } var rcv string - expected := `{"sessions":{"accounts_conns":[],"actions_conns":[],"alterable_fields":[],"attributes_conns":["*localhost"],"cdrs_conns":["*internal"],"channel_sync_interval":"0","chargers_conns":["*localhost"],"client_protocol":1,"debit_interval":"0","default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":true,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","opts":{"*accountS":[],"*attributeS":[],"*attributesDerivedReply":[],"*blockerError":[],"*cdrS":[],"*cdrsDerivedReply":[],"*chargeable":[],"*chargerS":[],"*debitInterval":[],"*forceDuration":[],"*initiate":[],"*lastUsage":[],"*lastUsed":[],"*maxDelay":[],"*maxUsage":[],"*message":[],"*resourceS":[],"*resourcesAllocate":[],"*resourcesAuthorize":[],"*resourcesDerivedReply":[],"*resourcesRelease":[],"*routeS":[],"*routesDerivedReply":[],"*statS":[],"*statsDerivedReply":[],"*terminate":[],"*thresholdS":[],"*thresholdsDerivedReply":[],"*ttl":[],"*update":[],"*usage":[]},"rates_conns":[],"replication_conns":[],"resources_conns":["*localhost"],"routes_conns":["*localhost"],"session_indexes":[],"session_ttl":"0","stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}` + expected := `{"sessions":{"accounts_conns":[],"actions_conns":[],"alterable_fields":[],"attributes_conns":["*localhost"],"cdrs_conns":["*internal"],"channel_sync_interval":"0","chargers_conns":["*localhost"],"client_protocol":1,"default_usage":{"*any":"3h0m0s","*data":"1048576","*sms":"1","*voice":"3h0m0s"},"enabled":true,"listen_bigob":"","listen_bijson":"127.0.0.1:2014","min_dur_low_balance":"0","opts":{"*accountS":[],"*attributeS":[],"*attributesDerivedReply":[],"*blockerError":[],"*cdrS":[],"*cdrsDerivedReply":[],"*chargeable":[],"*chargerS":[],"*debitInterval":[],"*forceDuration":[],"*initiate":[],"*maxUsage":[],"*message":[],"*resourceS":[],"*resourcesAllocate":[],"*resourcesAuthorize":[],"*resourcesDerivedReply":[],"*resourcesRelease":[],"*routeS":[],"*routesDerivedReply":[],"*statS":[],"*statsDerivedReply":[],"*terminate":[],"*thresholdS":[],"*thresholdsDerivedReply":[],"*ttl":[],"*ttlLastUsage":[],"*ttlLastUsed":[],"*ttlMaxDelay":[],"*ttlUsage":[],"*update":[]},"rates_conns":[],"replication_conns":[],"resources_conns":["*localhost"],"routes_conns":["*localhost"],"session_indexes":[],"stats_conns":[],"stir":{"allowed_attest":["*any"],"default_attest":"A","payload_maxduration":"-1","privatekey_path":"","publickey_path":""},"store_session_costs":false,"terminate_attempts":5,"thresholds_conns":[]}}` if err := cfg.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Sections: []string{SessionSJSON}}, &rcv); err != nil { t.Error(err) } else if expected != rcv { diff --git a/config/config_json_test.go b/config/config_json_test.go index c846b9bae..4392cf554 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -1719,7 +1719,7 @@ func TestDfHttpJsonCfg(t *testing.T) { Use_basic_auth: utils.BoolPointer(false), Auth_users: utils.MapStringStringPointer(map[string]string{}), Client_opts: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, diff --git a/config/config_test.go b/config/config_test.go index dcc63f93f..1ac6ec4ac 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -3956,7 +3956,7 @@ func TestV1GetConfigHTTP(t *testing.T) { utils.HTTPUseBasicAuthCfg: false, utils.HTTPAuthUsersCfg: map[string]string{}, utils.HTTPClientOptsCfg: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, @@ -5080,7 +5080,7 @@ func TestV1GetConfigAsJSONAccounts(t *testing.T) { func TestV1GetConfigAsJSONHTTP(t *testing.T) { var reply string - expected := `{"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0","forceAttemptHttp2":true,"idleConnTimeout":"90s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0","skipTlsVerify":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"}}` + expected := `{"http":{"auth_users":{},"client_opts":{"dialFallbackDelay":"300ms","dialKeepAlive":"30s","dialTimeout":"30s","disableCompression":false,"disableKeepAlives":false,"expectContinueTimeout":"0","forceAttemptHttp2":true,"idleConnTimeout":"90s","maxConnsPerHost":0,"maxIdleConns":100,"maxIdleConnsPerHost":2,"responseHeaderTimeout":"0","skipTLSVerification":false,"tlsHandshakeTimeout":"10s"},"freeswitch_cdrs_url":"/freeswitch_json","http_cdrs":"/cdr_http","json_rpc_url":"/jsonrpc","registrars_url":"/registrar","use_basic_auth":false,"ws_url":"/ws"}}` cfgCgr := NewDefaultCGRConfig() if err := cfgCgr.V1GetConfigAsJSON(context.Background(), &SectionWithAPIOpts{Sections: []string{HTTPJSON}}, &reply); err != nil { t.Error(err) diff --git a/config/httpcfg.go b/config/httpcfg.go index e41d4ef5f..72fc813b1 100644 --- a/config/httpcfg.go +++ b/config/httpcfg.go @@ -19,10 +19,19 @@ along with this program. If not, see package config import ( + "crypto/tls" + "net" + "net/http" + "github.com/cgrates/birpc/context" "github.com/cgrates/cgrates/utils" ) +type HTTPClientOpts struct { + Transport *http.Transport + Dialer *net.Dialer +} + // HTTPCfg is the HTTP config section type HTTPCfg struct { JsonRPCURL string // JSON RPC relative URL ("" to disable) @@ -32,7 +41,7 @@ type HTTPCfg struct { CDRsURL string // CDRS relative URL ("" to disable) UseBasicAuth bool // Use basic auth for HTTP API AuthUsers map[string]string // Basic auth user:password map (base64 passwords) - ClientOpts map[string]interface{} + ClientOpts *HTTPClientOpts } // loadHTTPCfg loads the Http section of the configuration @@ -44,6 +53,86 @@ func (httpcfg *HTTPCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig return httpcfg.loadFromJSONCfg(jsnHTTPCfg) } +func newDialer(jsnCfg *HTTPClientOptsJson) (dialer *net.Dialer, err error) { + if jsnCfg == nil { + return + } + dialer = &net.Dialer{ + DualStack: true, + } + if jsnCfg.DialTimeout != nil { + if dialer.Timeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.DialTimeout); err != nil { + return + } + } + if jsnCfg.DialFallbackDelay != nil { + if dialer.FallbackDelay, err = utils.ParseDurationWithNanosecs(*jsnCfg.DialFallbackDelay); err != nil { + return + } + } + if jsnCfg.DialKeepAlive != nil { + if dialer.KeepAlive, err = utils.ParseDurationWithNanosecs(*jsnCfg.DialKeepAlive); err != nil { + return + } + } + return +} + +func (httpOpts *HTTPClientOpts) loadFromJSONCfg(jsnCfg *HTTPClientOptsJson) (err error) { + if jsnCfg == nil { + return + } + httpOpts.Transport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + } + if jsnCfg.SkipTLSVerification != nil { + httpOpts.Transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: *jsnCfg.SkipTLSVerification} + } + if jsnCfg.TLSHandshakeTimeout != nil { + if httpOpts.Transport.TLSHandshakeTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.TLSHandshakeTimeout); err != nil { + return + } + } + if jsnCfg.DisableKeepAlives != nil { + httpOpts.Transport.DisableKeepAlives = *jsnCfg.DisableKeepAlives + } + if jsnCfg.DisableCompression != nil { + httpOpts.Transport.DisableCompression = *jsnCfg.DisableCompression + } + if jsnCfg.MaxIdleConns != nil { + httpOpts.Transport.MaxIdleConns = *jsnCfg.MaxIdleConns + } + if jsnCfg.MaxIdleConnsPerHost != nil { + httpOpts.Transport.MaxIdleConnsPerHost = *jsnCfg.MaxIdleConnsPerHost + } + if jsnCfg.MaxConnsPerHost != nil { + httpOpts.Transport.MaxConnsPerHost = *jsnCfg.MaxConnsPerHost + } + if jsnCfg.IdleConnTimeout != nil { + if httpOpts.Transport.IdleConnTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.IdleConnTimeout); err != nil { + return + } + } + if jsnCfg.ResponseHeaderTimeout != nil { + if httpOpts.Transport.ResponseHeaderTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.ResponseHeaderTimeout); err != nil { + return + } + } + if jsnCfg.ExpectContinueTimeout != nil { + if httpOpts.Transport.ExpectContinueTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.ExpectContinueTimeout); err != nil { + return + } + } + if jsnCfg.ForceAttemptHTTP2 != nil { + httpOpts.Transport.ForceAttemptHTTP2 = *jsnCfg.ForceAttemptHTTP2 + } + if httpOpts.Dialer, err = newDialer(jsnCfg); err != nil { + return + } + httpOpts.Transport.DialContext = httpOpts.Dialer.DialContext + return +} + // loadFromJSONCfg loads Database config from JsonCfg func (httpcfg *HTTPCfg) loadFromJSONCfg(jsnHTTPCfg *HTTPJsonCfg) (err error) { if jsnHTTPCfg == nil { @@ -71,18 +160,28 @@ func (httpcfg *HTTPCfg) loadFromJSONCfg(jsnHTTPCfg *HTTPJsonCfg) (err error) { httpcfg.AuthUsers = *jsnHTTPCfg.Auth_users } if jsnHTTPCfg.Client_opts != nil { - for k, v := range jsnHTTPCfg.Client_opts { - httpcfg.ClientOpts[k] = v - } + err = httpcfg.ClientOpts.loadFromJSONCfg(jsnHTTPCfg.Client_opts) } return nil } // AsMapInterface returns the config as a map[string]interface{} func (httpcfg HTTPCfg) AsMapInterface(string) interface{} { - clientOpts := make(map[string]interface{}) - for k, v := range httpcfg.ClientOpts { - clientOpts[k] = v + clientOpts := map[string]interface{}{ + utils.HTTPClientSkipTLSVerificationCfg: httpcfg.ClientOpts.Transport.TLSClientConfig.InsecureSkipVerify, + utils.HTTPClientTLSHandshakeTimeoutCfg: httpcfg.ClientOpts.Transport.TLSHandshakeTimeout, + utils.HTTPClientDisableKeepAlivesCfg: httpcfg.ClientOpts.Transport.DisableKeepAlives, + utils.HTTPClientDisableCompressionCfg: httpcfg.ClientOpts.Transport.DisableCompression, + utils.HTTPClientMaxIdleConnsCfg: httpcfg.ClientOpts.Transport.MaxIdleConns, + utils.HTTPClientMaxIdleConnsPerHostCfg: httpcfg.ClientOpts.Transport.MaxIdleConnsPerHost, + utils.HTTPClientMaxConnsPerHostCfg: httpcfg.ClientOpts.Transport.MaxConnsPerHost, + utils.HTTPClientIdleConnTimeoutCfg: httpcfg.ClientOpts.Transport.IdleConnTimeout, + utils.HTTPClientResponseHeaderTimeoutCfg: httpcfg.ClientOpts.Transport.ResponseHeaderTimeout, + utils.HTTPClientExpectContinueTimeoutCfg: httpcfg.ClientOpts.Transport.ExpectContinueTimeout, + utils.HTTPClientForceAttemptHTTP2Cfg: httpcfg.ClientOpts.Transport.ForceAttemptHTTP2, + utils.HTTPClientDialTimeoutCfg: httpcfg.ClientOpts.Dialer.Timeout, + utils.HTTPClientDialFallbackDelayCfg: httpcfg.ClientOpts.Dialer.FallbackDelay, + utils.HTTPClientDialKeepAliveCfg: httpcfg.ClientOpts.Dialer.KeepAlive, } return map[string]interface{}{ utils.HTTPJsonRPCURLCfg: httpcfg.JsonRPCURL, @@ -99,6 +198,33 @@ func (httpcfg HTTPCfg) AsMapInterface(string) interface{} { func (HTTPCfg) SName() string { return HTTPJSON } func (httpcfg HTTPCfg) CloneSection() Section { return httpcfg.Clone() } +func (httpOpts *HTTPClientOpts) Clone() (cln *HTTPClientOpts) { + transport := &http.Transport{ + Proxy: httpOpts.Transport.Proxy, + TLSClientConfig: httpOpts.Transport.TLSClientConfig, + TLSHandshakeTimeout: httpOpts.Transport.TLSHandshakeTimeout, + DisableKeepAlives: httpOpts.Transport.DisableKeepAlives, + DisableCompression: httpOpts.Transport.DisableCompression, + MaxIdleConns: httpOpts.Transport.MaxIdleConns, + MaxIdleConnsPerHost: httpOpts.Transport.MaxIdleConnsPerHost, + MaxConnsPerHost: httpOpts.Transport.MaxConnsPerHost, + IdleConnTimeout: httpOpts.Transport.IdleConnTimeout, + ResponseHeaderTimeout: httpOpts.Transport.ResponseHeaderTimeout, + ExpectContinueTimeout: httpOpts.Transport.ExpectContinueTimeout, + ForceAttemptHTTP2: httpOpts.Transport.ForceAttemptHTTP2, + } + dialer := &net.Dialer{ + Timeout: httpOpts.Dialer.Timeout, + DualStack: httpOpts.Dialer.DualStack, + KeepAlive: httpOpts.Dialer.KeepAlive, + FallbackDelay: httpOpts.Dialer.FallbackDelay, + } + return &HTTPClientOpts{ + Transport: transport, + Dialer: dialer, + } +} + // Clone returns a deep copy of HTTPCfg func (httpcfg HTTPCfg) Clone() (cln *HTTPCfg) { cln = &HTTPCfg{ @@ -109,17 +235,31 @@ func (httpcfg HTTPCfg) Clone() (cln *HTTPCfg) { CDRsURL: httpcfg.CDRsURL, UseBasicAuth: httpcfg.UseBasicAuth, AuthUsers: make(map[string]string), - ClientOpts: make(map[string]interface{}), + ClientOpts: httpcfg.ClientOpts.Clone(), } for u, a := range httpcfg.AuthUsers { cln.AuthUsers[u] = a } - for o, val := range httpcfg.ClientOpts { - cln.ClientOpts[o] = val - } return } +type HTTPClientOptsJson struct { + SkipTLSVerification *bool `json:"skipTLSVerification"` + TLSHandshakeTimeout *string `json:"tlsHandshakeTimeout"` + DisableKeepAlives *bool `json:"disableKeepAlives"` + DisableCompression *bool `json:"disableCompression"` + MaxIdleConns *int `json:"maxIdleConns"` + MaxIdleConnsPerHost *int `json:"maxConnsPerHost"` + MaxConnsPerHost *int `json:"maxConnsPerHost"` + IdleConnTimeout *string `json:"IdleConnTimeout"` + ResponseHeaderTimeout *string `json:"responseHeaderTimeout"` + ExpectContinueTimeout *string `json:"expectContinueTransport"` + ForceAttemptHTTP2 *bool `json:"forceAttemptHttp2"` + DialTimeout *string `json:"dialTimeout"` + DialFallbackDelay *string `json:"dialFallbackDelay"` + DialKeepAlive *string `json:"dialKeepAlive"` +} + // HTTP config section type HTTPJsonCfg struct { Json_rpc_url *string @@ -129,9 +269,57 @@ type HTTPJsonCfg struct { Http_Cdrs *string Use_basic_auth *bool Auth_users *map[string]string - Client_opts map[string]interface{} + Client_opts *HTTPClientOptsJson } +func diffHTTPClientOptsJsonCfg(d *HTTPClientOptsJson, v1, v2 *HTTPClientOpts) *HTTPClientOptsJson { + if d == nil { + d = new(HTTPClientOptsJson) + } + if v1.Transport.TLSClientConfig.InsecureSkipVerify != v2.Transport.TLSClientConfig.InsecureSkipVerify { + d.SkipTLSVerification = utils.BoolPointer(v2.Transport.TLSClientConfig.InsecureSkipVerify) + } + if v1.Transport.TLSHandshakeTimeout != v2.Transport.TLSHandshakeTimeout { + d.TLSHandshakeTimeout = utils.StringPointer(v2.Transport.TLSHandshakeTimeout.String()) + } + if v1.Transport.DisableKeepAlives != v2.Transport.DisableKeepAlives { + d.DisableKeepAlives = utils.BoolPointer(v2.Transport.DisableKeepAlives) + } + if v1.Transport.DisableCompression != v2.Transport.DisableCompression { + d.DisableCompression = utils.BoolPointer(v2.Transport.DisableCompression) + } + if v1.Transport.MaxIdleConns != v2.Transport.MaxIdleConns { + d.MaxIdleConns = utils.IntPointer(v2.Transport.MaxIdleConns) + } + if v1.Transport.MaxIdleConnsPerHost != v2.Transport.MaxIdleConnsPerHost { + d.MaxIdleConnsPerHost = utils.IntPointer(v2.Transport.MaxIdleConnsPerHost) + } + if v1.Transport.MaxConnsPerHost != v2.Transport.MaxConnsPerHost { + d.MaxConnsPerHost = utils.IntPointer(v2.Transport.MaxConnsPerHost) + } + if v1.Transport.IdleConnTimeout != v2.Transport.IdleConnTimeout { + d.IdleConnTimeout = utils.StringPointer(v2.Transport.IdleConnTimeout.String()) + } + if v1.Transport.ResponseHeaderTimeout != v2.Transport.ResponseHeaderTimeout { + d.ResponseHeaderTimeout = utils.StringPointer(v2.Transport.ResponseHeaderTimeout.String()) + } + if v1.Transport.ExpectContinueTimeout != v2.Transport.ExpectContinueTimeout { + d.ExpectContinueTimeout = utils.StringPointer(v2.Transport.ExpectContinueTimeout.String()) + } + if v1.Transport.ForceAttemptHTTP2 != v2.Transport.ForceAttemptHTTP2 { + d.ForceAttemptHTTP2 = utils.BoolPointer(v2.Transport.ForceAttemptHTTP2) + } + if v1.Dialer.Timeout != v2.Dialer.Timeout { + d.DialTimeout = utils.StringPointer(v2.Dialer.Timeout.String()) + } + if v1.Dialer.FallbackDelay != v2.Dialer.FallbackDelay { + d.DialFallbackDelay = utils.StringPointer(v2.Dialer.FallbackDelay.String()) + } + if v1.Dialer.KeepAlive != v2.Dialer.KeepAlive { + d.DialKeepAlive = utils.StringPointer(v2.Dialer.KeepAlive.String()) + } + return d +} func diffHTTPJsonCfg(d *HTTPJsonCfg, v1, v2 *HTTPCfg) *HTTPJsonCfg { if d == nil { d = new(HTTPJsonCfg) @@ -158,7 +346,7 @@ func diffHTTPJsonCfg(d *HTTPJsonCfg, v1, v2 *HTTPCfg) *HTTPJsonCfg { if !utils.MapStringStringEqual(v1.AuthUsers, v2.AuthUsers) { d.Auth_users = &v2.AuthUsers } - d.Client_opts = diffMap(d.Client_opts, v1.ClientOpts, v2.ClientOpts) + d.Client_opts = diffHTTPClientOptsJsonCfg(d.Client_opts, v1.ClientOpts, v2.ClientOpts) return d } diff --git a/config/httpcfg_test.go b/config/httpcfg_test.go index c59316ecd..ae7326417 100644 --- a/config/httpcfg_test.go +++ b/config/httpcfg_test.go @@ -43,7 +43,7 @@ func TestHTTPCfgloadFromJsonCfg(t *testing.T) { UseBasicAuth: false, AuthUsers: map[string]string{}, ClientOpts: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, @@ -85,7 +85,7 @@ func TestHTTPCfgAsMapInterface(t *testing.T) { utils.HTTPUseBasicAuthCfg: false, utils.HTTPAuthUsersCfg: map[string]string{}, utils.HTTPClientOptsCfg: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, @@ -129,7 +129,7 @@ func TestHTTPCfgAsMapInterface1(t *testing.T) { "user2": "authenticated", }, utils.HTTPClientOptsCfg: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, @@ -164,14 +164,14 @@ func TestHTTPCfgClone(t *testing.T) { "user": "pass", }, ClientOpts: map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, }, } rcv := ban.Clone() if !reflect.DeepEqual(ban, rcv) { t.Errorf("Expected: %+v\nReceived: %+v", utils.ToJSON(ban), utils.ToJSON(rcv)) } - if rcv.ClientOpts[utils.HTTPClientTLSClientConfigCfg] = ""; ban.ClientOpts[utils.HTTPClientTLSClientConfigCfg] != false { + if rcv.ClientOpts[utils.HTTPClientSkipTLSVerificationCfg] = ""; ban.ClientOpts[utils.HTTPClientSkipTLSVerificationCfg] != false { t.Errorf("Expected clone to not modify the cloned") } if rcv.AuthUsers["user"] = ""; ban.AuthUsers["user"] != "pass" { diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index f52861024..812038567 100755 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -176,7 +176,7 @@ // "use_basic_auth": false, // use basic authentication // "auth_users": {}, // basic authentication usernames and base64-encoded passwords (eg: { "username1": "cGFzc3dvcmQ=", "username2": "cGFzc3dvcmQy "}) // "client_opts":{ -// "skipTlsVerify": false, // if enabled Http Client will accept any TLS certificate +// "skipTLSVerification": false, // if enabled Http Client will accept any TLS certificate // // the options to configure the http.Transport // "tlsHandshakeTimeout": "10s", // "disableKeepAlives": false, diff --git a/engine/globalvars.go b/engine/globalvars.go index 02f426520..1db6799d7 100644 --- a/engine/globalvars.go +++ b/engine/globalvars.go @@ -16,13 +16,9 @@ along with this program. If not, see package engine import ( - "crypto/tls" - "net" "net/http" - "time" "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" ) // this file will contain all the global variable that are used by other subsystems @@ -33,7 +29,7 @@ var ( ) func init() { - httpPstrTransport, _ = NewHTTPTransport(config.CgrConfig().HTTPCfg().ClientOpts) + httpPstrTransport = config.CgrConfig().HTTPCfg().ClientOpts.Transport } // SetConnManager is the exported method to set the connectionManager used when operate on an account. @@ -50,122 +46,3 @@ func SetHTTPPstrTransport(pstrTransport *http.Transport) { func GetHTTPPstrTransport() *http.Transport { return httpPstrTransport } - -// NewHTTPTransport will create a new transport for HTTP client -func NewHTTPTransport(opts map[string]interface{}) (trsp *http.Transport, err error) { - trsp = &http.Transport{ - Proxy: http.ProxyFromEnvironment, - } - if val, has := opts[utils.HTTPClientTLSClientConfigCfg]; has { - var skipTLSVerify bool - if skipTLSVerify, err = utils.IfaceAsBool(val); err != nil { - return - } - trsp.TLSClientConfig = &tls.Config{InsecureSkipVerify: skipTLSVerify} - } - if val, has := opts[utils.HTTPClientTLSHandshakeTimeoutCfg]; has { - var tlsHndTimeout time.Duration - if tlsHndTimeout, err = utils.IfaceAsDuration(val); err != nil { - return - } - trsp.TLSHandshakeTimeout = tlsHndTimeout - } - if val, has := opts[utils.HTTPClientDisableKeepAlivesCfg]; has { - var disKeepAlives bool - if disKeepAlives, err = utils.IfaceAsBool(val); err != nil { - return - } - trsp.DisableKeepAlives = disKeepAlives - } - if val, has := opts[utils.HTTPClientDisableCompressionCfg]; has { - var disCmp bool - if disCmp, err = utils.IfaceAsBool(val); err != nil { - return - } - trsp.DisableCompression = disCmp - } - if val, has := opts[utils.HTTPClientMaxIdleConnsCfg]; has { - var maxIdleConns int64 - if maxIdleConns, err = utils.IfaceAsTInt64(val); err != nil { - return - } - trsp.MaxIdleConns = int(maxIdleConns) - } - if val, has := opts[utils.HTTPClientMaxIdleConnsPerHostCfg]; has { - var maxIdleConns int64 - if maxIdleConns, err = utils.IfaceAsTInt64(val); err != nil { - return - } - trsp.MaxIdleConnsPerHost = int(maxIdleConns) - } - if val, has := opts[utils.HTTPClientMaxConnsPerHostCfg]; has { - var maxConns int64 - if maxConns, err = utils.IfaceAsTInt64(val); err != nil { - return - } - trsp.MaxConnsPerHost = int(maxConns) - } - if val, has := opts[utils.HTTPClientIdleConnTimeoutCfg]; has { - var idleTimeout time.Duration - if idleTimeout, err = utils.IfaceAsDuration(val); err != nil { - return - } - trsp.IdleConnTimeout = idleTimeout - } - if val, has := opts[utils.HTTPClientResponseHeaderTimeoutCfg]; has { - var responseTimeout time.Duration - if responseTimeout, err = utils.IfaceAsDuration(val); err != nil { - return - } - trsp.ResponseHeaderTimeout = responseTimeout - } - if val, has := opts[utils.HTTPClientExpectContinueTimeoutCfg]; has { - var continueTimeout time.Duration - if continueTimeout, err = utils.IfaceAsDuration(val); err != nil { - return - } - trsp.ExpectContinueTimeout = continueTimeout - } - if val, has := opts[utils.HTTPClientForceAttemptHTTP2Cfg]; has { - var forceHTTP2 bool - if forceHTTP2, err = utils.IfaceAsBool(val); err != nil { - return - } - trsp.ForceAttemptHTTP2 = forceHTTP2 - } - var dial *net.Dialer - if dial, err = newDialer(opts); err != nil { - return - } - trsp.DialContext = dial.DialContext - return -} - -// newDialer returns the objects that creates the DialContext function -func newDialer(opts map[string]interface{}) (dial *net.Dialer, err error) { - dial = &net.Dialer{ - DualStack: true, - } - if val, has := opts[utils.HTTPClientDialTimeoutCfg]; has { - var timeout time.Duration - if timeout, err = utils.IfaceAsDuration(val); err != nil { - return - } - dial.Timeout = timeout - } - if val, has := opts[utils.HTTPClientDialFallbackDelayCfg]; has { - var fallDelay time.Duration - if fallDelay, err = utils.IfaceAsDuration(val); err != nil { - return - } - dial.FallbackDelay = fallDelay - } - if val, has := opts[utils.HTTPClientDialKeepAliveCfg]; has { - var keepAlive time.Duration - if keepAlive, err = utils.IfaceAsDuration(val); err != nil { - return - } - dial.KeepAlive = keepAlive - } - return -} diff --git a/engine/globalvars_test.go b/engine/globalvars_test.go index 6880a150b..52190e4fc 100644 --- a/engine/globalvars_test.go +++ b/engine/globalvars_test.go @@ -29,7 +29,7 @@ import ( func TestNewHTTPTransport(t *testing.T) { opts := map[string]interface{}{ - utils.HTTPClientTLSClientConfigCfg: false, + utils.HTTPClientSkipTLSVerificationCfg: false, utils.HTTPClientTLSHandshakeTimeoutCfg: "10s", utils.HTTPClientDisableKeepAlivesCfg: false, utils.HTTPClientDisableCompressionCfg: false, @@ -138,7 +138,7 @@ func TestNewHTTPTransport(t *testing.T) { if _, err := NewHTTPTransport(opts); err == nil { t.Error("Expected error but the transport was builded succesfully") } - opts[utils.HTTPClientTLSClientConfigCfg] = "string" + opts[utils.HTTPClientSkipTLSVerificationCfg] = "string" if _, err := NewHTTPTransport(opts); err == nil { t.Error("Expected error but the transport was builded succesfully") } diff --git a/general_tests/all_cfg_rld_it_test.go b/general_tests/all_cfg_rld_it_test.go index 5de6b5f26..4611af0a8 100644 --- a/general_tests/all_cfg_rld_it_test.go +++ b/general_tests/all_cfg_rld_it_test.go @@ -155,7 +155,7 @@ package general_tests // t.Errorf("\nExpected %+v ,\n received: %+v", utils.ToIJSON(cfgStr), utils.ToIJSON(rpl4)) // } -// cfgStr = "{\"http\":{\"auth_users\":{},\"client_opts\":{\"dialFallbackDelay\":\"300ms\",\"dialKeepAlive\":\"30s\",\"dialTimeout\":\"30s\",\"disableCompression\":false,\"disableKeepAlives\":false,\"expectContinueTimeout\":\"0\",\"forceAttemptHttp2\":true,\"idleConnTimeout\":\"90s\",\"maxConnsPerHost\":0,\"maxIdleConns\":100,\"maxIdleConnsPerHost\":2,\"responseHeaderTimeout\":\"0\",\"skipTlsVerify\":false,\"tlsHandshakeTimeout\":\"10s\"},\"freeswitch_cdrs_url\":\"/freeswitch_json\",\"http_cdrs\":\"/cdr_http\",\"json_rpc_url\":\"/jsonrpc\",\"registrars_url\":\"/registrar\",\"use_basic_auth\":false,\"ws_url\":\"/ws\"}}" +// cfgStr = "{\"http\":{\"auth_users\":{},\"client_opts\":{\"dialFallbackDelay\":\"300ms\",\"dialKeepAlive\":\"30s\",\"dialTimeout\":\"30s\",\"disableCompression\":false,\"disableKeepAlives\":false,\"expectContinueTimeout\":\"0\",\"forceAttemptHttp2\":true,\"idleConnTimeout\":\"90s\",\"maxConnsPerHost\":0,\"maxIdleConns\":100,\"maxIdleConnsPerHost\":2,\"responseHeaderTimeout\":\"0\",\"skipTLSVerification\":false,\"tlsHandshakeTimeout\":\"10s\"},\"freeswitch_cdrs_url\":\"/freeswitch_json\",\"http_cdrs\":\"/cdr_http\",\"json_rpc_url\":\"/jsonrpc\",\"registrars_url\":\"/registrar\",\"use_basic_auth\":false,\"ws_url\":\"/ws\"}}" // var rpl5 string // if err := testRPC.Call(context.Background(), utils.ConfigSv1GetConfigAsJSON, &config.SectionWithAPIOpts{ diff --git a/services/globalvars.go b/services/globalvars.go index 70395beac..a7fc485db 100644 --- a/services/globalvars.go +++ b/services/globalvars.go @@ -19,8 +19,6 @@ along with this program. If not, see package services import ( - "fmt" - "net/http" "sync" "github.com/cgrates/birpc/context" @@ -50,12 +48,14 @@ type GlobalVarS struct { // Start should handle the sercive start func (gv *GlobalVarS) Start(*context.Context, context.CancelFunc) error { ees.SetFailedPostCacheTTL(gv.cfg.GeneralCfg().FailedPostsTTL) - return gv.initHTTPTransport() + engine.SetHTTPPstrTransport(gv.cfg.HTTPCfg().ClientOpts.Transport) + return nil } // Reload handles the change of config func (gv *GlobalVarS) Reload(*context.Context, context.CancelFunc) error { - return gv.initHTTPTransport() + engine.SetHTTPPstrTransport(gv.cfg.HTTPCfg().ClientOpts.Transport) + return nil } // Shutdown stops the service @@ -77,13 +77,3 @@ func (gv *GlobalVarS) ServiceName() string { func (gv *GlobalVarS) ShouldRun() bool { return true } - -func (gv *GlobalVarS) initHTTPTransport() (err error) { - var trsp *http.Transport - if trsp, err = engine.NewHTTPTransport(gv.cfg.HTTPCfg().ClientOpts); err != nil { - utils.Logger.Crit(fmt.Sprintf("Could not configure the http transport: %s exiting!", err)) - return - } - engine.SetHTTPPstrTransport(trsp) - return -} diff --git a/services/globalvars_it_test.go b/services/globalvars_it_test.go index d0cf2f481..1b8bcf586 100644 --- a/services/globalvars_it_test.go +++ b/services/globalvars_it_test.go @@ -55,13 +55,6 @@ func TestGlobalVarsReload(t *testing.T) { if err3 != true { t.Errorf("\nExpected <%+v>, \nReceived <%+v>", true, err3) } - cfg.HTTPCfg().ClientOpts = map[string]interface{}{ - utils.HTTPClientTLSHandshakeTimeoutCfg: false, - } - err = srv.(*GlobalVarS).initHTTPTransport() - if err == nil || err.Error() != "cannot convert field: false to time.Duration" { - t.Errorf("\nExpected , \nReceived <%+v>", err) - } err = srv.Shutdown() if err != nil { t.Errorf("\nExpected , \nReceived <%+v>", err) diff --git a/utils/consts.go b/utils/consts.go index c81a069d0..43557da0c 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -1786,7 +1786,7 @@ const ( HTTPAuthUsersCfg = "auth_users" HTTPClientOptsCfg = "client_opts" - HTTPClientTLSClientConfigCfg = "skipTlsVerify" + HTTPClientSkipTLSVerificationCfg = "skipTLSVerification" HTTPClientTLSHandshakeTimeoutCfg = "tlsHandshakeTimeout" HTTPClientDisableKeepAlivesCfg = "disableKeepAlives" HTTPClientDisableCompressionCfg = "disableCompression"