mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-16 05:39:54 +05:00
Make ClientOpts of type struct in httpcfg
This commit is contained in:
committed by
Dan Christian Bogos
parent
5a92ce47cb
commit
9ba6df7fc0
@@ -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{},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -19,10 +19,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -16,13 +16,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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 <nil>, \nReceived <%+v>", err)
|
||||
}
|
||||
err = srv.Shutdown()
|
||||
if err != nil {
|
||||
t.Errorf("\nExpected <nil>, \nReceived <%+v>", err)
|
||||
|
||||
@@ -1786,7 +1786,7 @@ const (
|
||||
HTTPAuthUsersCfg = "auth_users"
|
||||
HTTPClientOptsCfg = "client_opts"
|
||||
|
||||
HTTPClientTLSClientConfigCfg = "skipTlsVerify"
|
||||
HTTPClientSkipTLSVerificationCfg = "skipTLSVerification"
|
||||
HTTPClientTLSHandshakeTimeoutCfg = "tlsHandshakeTimeout"
|
||||
HTTPClientDisableKeepAlivesCfg = "disableKeepAlives"
|
||||
HTTPClientDisableCompressionCfg = "disableCompression"
|
||||
|
||||
Reference in New Issue
Block a user