mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
347 lines
12 KiB
Go
347 lines
12 KiB
Go
/*
|
|
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
|
Copyright (C) ITsysCOM GmbH
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
package config
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http"
|
|
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
// HTTPCfg is the HTTP config section
|
|
type HTTPCfg struct {
|
|
JsonRPCURL string // JSON RPC relative URL ("" to disable)
|
|
RegistrarSURL string // registrar service relative URL
|
|
WSURL string // WebSocket relative URL ("" to disable)
|
|
FreeswitchCDRsURL string // Freeswitch CDRS relative URL ("" to disable)
|
|
CDRsURL string // CDRS relative URL ("" to disable)
|
|
PprofPath string // runtime profiling url path ("" to disable)
|
|
UseBasicAuth bool // Use basic auth for HTTP API
|
|
AuthUsers map[string]string // Basic auth user:password map (base64 passwords)
|
|
ClientOpts *http.Transport
|
|
dialer *net.Dialer
|
|
}
|
|
|
|
// loadHTTPCfg loads the Http section of the configuration
|
|
func (httpcfg *HTTPCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) {
|
|
jsnHTTPCfg := new(HTTPJsonCfg)
|
|
if err = jsnCfg.GetSection(ctx, HTTPJSON, jsnHTTPCfg); err != nil {
|
|
return
|
|
}
|
|
return httpcfg.loadFromJSONCfg(jsnHTTPCfg)
|
|
}
|
|
|
|
func newDialer(dialer *net.Dialer, jsnCfg *HTTPClientOptsJson) (err error) {
|
|
if jsnCfg == nil {
|
|
return
|
|
}
|
|
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 loadTransportFromJSONCfg(httpOpts *http.Transport, httpDialer *net.Dialer, jsnCfg *HTTPClientOptsJson) (err error) {
|
|
if jsnCfg == nil {
|
|
return
|
|
}
|
|
httpOpts.Proxy = http.ProxyFromEnvironment
|
|
if jsnCfg.SkipTLSVerification != nil {
|
|
httpOpts.TLSClientConfig = &tls.Config{InsecureSkipVerify: *jsnCfg.SkipTLSVerification}
|
|
}
|
|
if jsnCfg.TLSHandshakeTimeout != nil {
|
|
if httpOpts.TLSHandshakeTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.TLSHandshakeTimeout); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if jsnCfg.DisableKeepAlives != nil {
|
|
httpOpts.DisableKeepAlives = *jsnCfg.DisableKeepAlives
|
|
}
|
|
if jsnCfg.DisableCompression != nil {
|
|
httpOpts.DisableCompression = *jsnCfg.DisableCompression
|
|
}
|
|
if jsnCfg.MaxIdleConns != nil {
|
|
httpOpts.MaxIdleConns = *jsnCfg.MaxIdleConns
|
|
}
|
|
if jsnCfg.MaxIdleConnsPerHost != nil {
|
|
httpOpts.MaxIdleConnsPerHost = *jsnCfg.MaxIdleConnsPerHost
|
|
}
|
|
if jsnCfg.MaxConnsPerHost != nil {
|
|
httpOpts.MaxConnsPerHost = *jsnCfg.MaxConnsPerHost
|
|
}
|
|
if jsnCfg.IdleConnTimeout != nil {
|
|
if httpOpts.IdleConnTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.IdleConnTimeout); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if jsnCfg.ResponseHeaderTimeout != nil {
|
|
if httpOpts.ResponseHeaderTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.ResponseHeaderTimeout); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if jsnCfg.ExpectContinueTimeout != nil {
|
|
if httpOpts.ExpectContinueTimeout, err = utils.ParseDurationWithNanosecs(*jsnCfg.ExpectContinueTimeout); err != nil {
|
|
return
|
|
}
|
|
}
|
|
if jsnCfg.ForceAttemptHTTP2 != nil {
|
|
httpOpts.ForceAttemptHTTP2 = *jsnCfg.ForceAttemptHTTP2
|
|
}
|
|
httpOpts.DialContext = httpDialer.DialContext
|
|
return
|
|
}
|
|
|
|
// loadFromJSONCfg loads Database config from JsonCfg
|
|
func (httpcfg *HTTPCfg) loadFromJSONCfg(jsnHTTPCfg *HTTPJsonCfg) (err error) {
|
|
if jsnHTTPCfg == nil {
|
|
return
|
|
}
|
|
if jsnHTTPCfg.JSONRPCURL != nil {
|
|
httpcfg.JsonRPCURL = *jsnHTTPCfg.JSONRPCURL
|
|
}
|
|
if jsnHTTPCfg.RegistrarsURL != nil {
|
|
httpcfg.RegistrarSURL = *jsnHTTPCfg.RegistrarsURL
|
|
}
|
|
if jsnHTTPCfg.WSURL != nil {
|
|
httpcfg.WSURL = *jsnHTTPCfg.WSURL
|
|
}
|
|
if jsnHTTPCfg.FreeswitchCDRsURL != nil {
|
|
httpcfg.FreeswitchCDRsURL = *jsnHTTPCfg.FreeswitchCDRsURL
|
|
}
|
|
if jsnHTTPCfg.HTTPCDRs != nil {
|
|
httpcfg.CDRsURL = *jsnHTTPCfg.HTTPCDRs
|
|
}
|
|
if jsnHTTPCfg.PprofPath != nil {
|
|
httpcfg.PprofPath = *jsnHTTPCfg.PprofPath
|
|
}
|
|
if jsnHTTPCfg.UseBasicAuth != nil {
|
|
httpcfg.UseBasicAuth = *jsnHTTPCfg.UseBasicAuth
|
|
}
|
|
if jsnHTTPCfg.AuthUsers != nil {
|
|
httpcfg.AuthUsers = *jsnHTTPCfg.AuthUsers
|
|
}
|
|
if jsnHTTPCfg.ClientOpts != nil {
|
|
if err = newDialer(httpcfg.dialer, jsnHTTPCfg.ClientOpts); err != nil {
|
|
return
|
|
}
|
|
err = loadTransportFromJSONCfg(httpcfg.ClientOpts, httpcfg.dialer, jsnHTTPCfg.ClientOpts)
|
|
}
|
|
return
|
|
}
|
|
|
|
// AsMapInterface returns the config as a map[string]any
|
|
func (httpcfg HTTPCfg) AsMapInterface() any {
|
|
clientOpts := map[string]any{
|
|
utils.HTTPClientSkipTLSVerificationCfg: false,
|
|
utils.HTTPClientTLSHandshakeTimeoutCfg: httpcfg.ClientOpts.TLSHandshakeTimeout.String(),
|
|
utils.HTTPClientDisableKeepAlivesCfg: httpcfg.ClientOpts.DisableKeepAlives,
|
|
utils.HTTPClientDisableCompressionCfg: httpcfg.ClientOpts.DisableCompression,
|
|
utils.HTTPClientMaxIdleConnsCfg: httpcfg.ClientOpts.MaxIdleConns,
|
|
utils.HTTPClientMaxIdleConnsPerHostCfg: httpcfg.ClientOpts.MaxIdleConnsPerHost,
|
|
utils.HTTPClientMaxConnsPerHostCfg: httpcfg.ClientOpts.MaxConnsPerHost,
|
|
utils.HTTPClientIdleConnTimeoutCfg: httpcfg.ClientOpts.IdleConnTimeout.String(),
|
|
utils.HTTPClientResponseHeaderTimeoutCfg: httpcfg.ClientOpts.ResponseHeaderTimeout.String(),
|
|
utils.HTTPClientExpectContinueTimeoutCfg: httpcfg.ClientOpts.ExpectContinueTimeout.String(),
|
|
utils.HTTPClientForceAttemptHTTP2Cfg: httpcfg.ClientOpts.ForceAttemptHTTP2,
|
|
utils.HTTPClientDialTimeoutCfg: httpcfg.dialer.Timeout.String(),
|
|
utils.HTTPClientDialFallbackDelayCfg: httpcfg.dialer.FallbackDelay.String(),
|
|
utils.HTTPClientDialKeepAliveCfg: httpcfg.dialer.KeepAlive.String(),
|
|
}
|
|
if httpcfg.ClientOpts.TLSClientConfig != nil {
|
|
clientOpts[utils.HTTPClientSkipTLSVerificationCfg] = httpcfg.ClientOpts.TLSClientConfig.InsecureSkipVerify
|
|
}
|
|
return map[string]any{
|
|
utils.HTTPJsonRPCURLCfg: httpcfg.JsonRPCURL,
|
|
utils.RegistrarSURLCfg: httpcfg.RegistrarSURL,
|
|
utils.HTTPWSURLCfg: httpcfg.WSURL,
|
|
utils.HTTPFreeswitchCDRsURLCfg: httpcfg.FreeswitchCDRsURL,
|
|
utils.HTTPCDRsURLCfg: httpcfg.CDRsURL,
|
|
utils.PprofPathCfg: httpcfg.PprofPath,
|
|
utils.HTTPUseBasicAuthCfg: httpcfg.UseBasicAuth,
|
|
utils.HTTPAuthUsersCfg: httpcfg.AuthUsers,
|
|
utils.HTTPClientOptsCfg: clientOpts,
|
|
}
|
|
}
|
|
|
|
func (HTTPCfg) SName() string { return HTTPJSON }
|
|
func (httpcfg HTTPCfg) CloneSection() Section { return httpcfg.Clone() }
|
|
|
|
// Clone returns a deep copy of HTTPCfg
|
|
func (httpcfg HTTPCfg) Clone() (cln *HTTPCfg) {
|
|
dialer := &net.Dialer{
|
|
Timeout: httpcfg.dialer.Timeout,
|
|
DualStack: httpcfg.dialer.DualStack,
|
|
KeepAlive: httpcfg.dialer.KeepAlive,
|
|
FallbackDelay: httpcfg.dialer.FallbackDelay,
|
|
}
|
|
cln = &HTTPCfg{
|
|
JsonRPCURL: httpcfg.JsonRPCURL,
|
|
RegistrarSURL: httpcfg.RegistrarSURL,
|
|
WSURL: httpcfg.WSURL,
|
|
FreeswitchCDRsURL: httpcfg.FreeswitchCDRsURL,
|
|
CDRsURL: httpcfg.CDRsURL,
|
|
PprofPath: httpcfg.PprofPath,
|
|
UseBasicAuth: httpcfg.UseBasicAuth,
|
|
AuthUsers: make(map[string]string),
|
|
ClientOpts: httpcfg.ClientOpts.Clone(),
|
|
dialer: dialer,
|
|
}
|
|
for u, a := range httpcfg.AuthUsers {
|
|
cln.AuthUsers[u] = a
|
|
}
|
|
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:"maxIdleConnsPerHost"`
|
|
MaxConnsPerHost *int `json:"maxConnsPerHost"`
|
|
IdleConnTimeout *string `json:"IdleConnTimeout"`
|
|
ResponseHeaderTimeout *string `json:"responseHeaderTimeout"`
|
|
ExpectContinueTimeout *string `json:"expectContinueTimeout"`
|
|
ForceAttemptHTTP2 *bool `json:"forceAttemptHttp2"`
|
|
DialTimeout *string `json:"dialTimeout"`
|
|
DialFallbackDelay *string `json:"dialFallbackDelay"`
|
|
DialKeepAlive *string `json:"dialKeepAlive"`
|
|
}
|
|
|
|
// HTTP config section
|
|
type HTTPJsonCfg struct {
|
|
JSONRPCURL *string `json:"json_rpc_url"`
|
|
RegistrarsURL *string `json:"registrars_url"`
|
|
WSURL *string `json:"ws_url"`
|
|
FreeswitchCDRsURL *string `json:"freeswitch_cdrs_url"`
|
|
HTTPCDRs *string `json:"http_cdrs"`
|
|
PprofPath *string `json:"pprof_path"`
|
|
UseBasicAuth *bool `json:"use_basic_auth"`
|
|
AuthUsers *map[string]string `json:"auth_users"`
|
|
ClientOpts *HTTPClientOptsJson `json:"client_opts"`
|
|
}
|
|
|
|
func diffHTTPClientOptsJsonCfgDialer(d *HTTPClientOptsJson, v1, v2 *net.Dialer) *HTTPClientOptsJson {
|
|
if d == nil {
|
|
d = new(HTTPClientOptsJson)
|
|
}
|
|
if v1.Timeout != v2.Timeout {
|
|
d.DialTimeout = utils.StringPointer(v2.Timeout.String())
|
|
}
|
|
if v1.FallbackDelay != v2.FallbackDelay {
|
|
d.DialFallbackDelay = utils.StringPointer(v2.FallbackDelay.String())
|
|
}
|
|
if v1.KeepAlive != v2.KeepAlive {
|
|
d.DialKeepAlive = utils.StringPointer(v2.KeepAlive.String())
|
|
}
|
|
return d
|
|
}
|
|
|
|
func diffHTTPClientOptsJsonCfg(d *HTTPClientOptsJson, v1, v2 *http.Transport) *HTTPClientOptsJson {
|
|
if d == nil {
|
|
d = new(HTTPClientOptsJson)
|
|
}
|
|
if v1.TLSClientConfig != nil {
|
|
if v1.TLSClientConfig.InsecureSkipVerify != v2.TLSClientConfig.InsecureSkipVerify {
|
|
d.SkipTLSVerification = utils.BoolPointer(v2.TLSClientConfig.InsecureSkipVerify)
|
|
}
|
|
}
|
|
if v1.TLSHandshakeTimeout != v2.TLSHandshakeTimeout {
|
|
d.TLSHandshakeTimeout = utils.StringPointer(v2.TLSHandshakeTimeout.String())
|
|
}
|
|
if v1.DisableKeepAlives != v2.DisableKeepAlives {
|
|
d.DisableKeepAlives = utils.BoolPointer(v2.DisableKeepAlives)
|
|
}
|
|
if v1.DisableCompression != v2.DisableCompression {
|
|
d.DisableCompression = utils.BoolPointer(v2.DisableCompression)
|
|
}
|
|
if v1.MaxIdleConns != v2.MaxIdleConns {
|
|
d.MaxIdleConns = utils.IntPointer(v2.MaxIdleConns)
|
|
}
|
|
if v1.MaxIdleConnsPerHost != v2.MaxIdleConnsPerHost {
|
|
d.MaxIdleConnsPerHost = utils.IntPointer(v2.MaxIdleConnsPerHost)
|
|
}
|
|
if v1.MaxConnsPerHost != v2.MaxConnsPerHost {
|
|
d.MaxConnsPerHost = utils.IntPointer(v2.MaxConnsPerHost)
|
|
}
|
|
if v1.IdleConnTimeout != v2.IdleConnTimeout {
|
|
d.IdleConnTimeout = utils.StringPointer(v2.IdleConnTimeout.String())
|
|
}
|
|
if v1.ResponseHeaderTimeout != v2.ResponseHeaderTimeout {
|
|
d.ResponseHeaderTimeout = utils.StringPointer(v2.ResponseHeaderTimeout.String())
|
|
}
|
|
if v1.ExpectContinueTimeout != v2.ExpectContinueTimeout {
|
|
d.ExpectContinueTimeout = utils.StringPointer(v2.ExpectContinueTimeout.String())
|
|
}
|
|
if v1.ForceAttemptHTTP2 != v2.ForceAttemptHTTP2 {
|
|
d.ForceAttemptHTTP2 = utils.BoolPointer(v2.ForceAttemptHTTP2)
|
|
}
|
|
return d
|
|
}
|
|
func diffHTTPJsonCfg(d *HTTPJsonCfg, v1, v2 *HTTPCfg) *HTTPJsonCfg {
|
|
if d == nil {
|
|
d = new(HTTPJsonCfg)
|
|
}
|
|
|
|
if v1.JsonRPCURL != v2.JsonRPCURL {
|
|
d.JSONRPCURL = utils.StringPointer(v2.JsonRPCURL)
|
|
}
|
|
if v1.RegistrarSURL != v2.RegistrarSURL {
|
|
d.RegistrarsURL = utils.StringPointer(v2.RegistrarSURL)
|
|
}
|
|
if v1.WSURL != v2.WSURL {
|
|
d.WSURL = utils.StringPointer(v2.WSURL)
|
|
}
|
|
if v1.FreeswitchCDRsURL != v2.FreeswitchCDRsURL {
|
|
d.FreeswitchCDRsURL = utils.StringPointer(v2.FreeswitchCDRsURL)
|
|
}
|
|
if v1.CDRsURL != v2.CDRsURL {
|
|
d.HTTPCDRs = utils.StringPointer(v2.CDRsURL)
|
|
}
|
|
if v1.PprofPath != v2.PprofPath {
|
|
d.PprofPath = utils.StringPointer(v2.PprofPath)
|
|
}
|
|
if v1.UseBasicAuth != v2.UseBasicAuth {
|
|
d.UseBasicAuth = utils.BoolPointer(v2.UseBasicAuth)
|
|
}
|
|
if !utils.MapStringStringEqual(v1.AuthUsers, v2.AuthUsers) {
|
|
d.AuthUsers = &v2.AuthUsers
|
|
}
|
|
d.ClientOpts = diffHTTPClientOptsJsonCfg(d.ClientOpts, v1.ClientOpts, v2.ClientOpts)
|
|
d.ClientOpts = diffHTTPClientOptsJsonCfgDialer(d.ClientOpts, v1.dialer, v2.dialer)
|
|
return d
|
|
}
|