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"