func ReadConfig(src map[string]string) config.Configuration {
	conf := map[string]string{}
	for k, v := range src {
		conf[k] = v
	}
	errors := make([]int, 0)
	skipUrls := make([]string, 0)
	whiteList := make([]string, 0)
	proxyList := make([]string, 0)
	hideHeadersList := make([]string, 0)
	bindAddressIpv4List := make([]string, 0)
	bindAddressIpv6List := make([]string, 0)
	redirectCode := 308
	if val, ok := conf[customHTTPErrors]; ok {
		delete(conf, customHTTPErrors)
		for _, i := range strings.Split(val, ",") {
			j, err := strconv.Atoi(i)
			if err != nil {
				glog.Warningf("%v is not a valid http code: %v", i, err)
			} else {
				errors = append(errors, j)
			}
		}
	}
	if val, ok := conf[hideHeaders]; ok {
		delete(conf, hideHeaders)
		hideHeadersList = strings.Split(val, ",")
	}
	if val, ok := conf[skipAccessLogUrls]; ok {
		delete(conf, skipAccessLogUrls)
		skipUrls = strings.Split(val, ",")
	}
	if val, ok := conf[whitelistSourceRange]; ok {
		delete(conf, whitelistSourceRange)
		whiteList = append(whiteList, strings.Split(val, ",")...)
	}
	if val, ok := conf[proxyRealIPCIDR]; ok {
		delete(conf, proxyRealIPCIDR)
		proxyList = append(proxyList, strings.Split(val, ",")...)
	} else {
		proxyList = append(proxyList, "0.0.0.0/0")
	}
	if val, ok := conf[bindAddress]; ok {
		delete(conf, bindAddress)
		for _, i := range strings.Split(val, ",") {
			ns := net.ParseIP(i)
			if ns != nil {
				if ing_net.IsIPV6(ns) {
					bindAddressIpv6List = append(bindAddressIpv6List, fmt.Sprintf("[%v]", ns))
				} else {
					bindAddressIpv4List = append(bindAddressIpv4List, fmt.Sprintf("%v", ns))
				}
			} else {
				glog.Warningf("%v is not a valid textual representation of an IP address", i)
			}
		}
	}
	if val, ok := conf[httpRedirectCode]; ok {
		delete(conf, httpRedirectCode)
		j, err := strconv.Atoi(val)
		if err != nil {
			glog.Warningf("%v is not a valid HTTP code: %v", val, err)
		} else {
			if validRedirectCodes.Has(j) {
				redirectCode = j
			} else {
				glog.Warningf("The code %v is not a valid as HTTP redirect code. Using the default.", val)
			}
		}
	}
	streamResponses := 1
	if val, ok := conf[proxyStreamResponses]; ok {
		delete(conf, proxyStreamResponses)
		j, err := strconv.Atoi(val)
		if err != nil {
			glog.Warningf("%v is not a valid number: %v", val, err)
		} else {
			streamResponses = j
		}
	}
	to := config.NewDefault()
	to.CustomHTTPErrors = filterErrors(errors)
	to.SkipAccessLogURLs = skipUrls
	to.WhitelistSourceRange = whiteList
	to.ProxyRealIPCIDR = proxyList
	to.BindAddressIpv4 = bindAddressIpv4List
	to.BindAddressIpv6 = bindAddressIpv6List
	to.HideHeaders = hideHeadersList
	to.HTTPRedirectCode = redirectCode
	to.ProxyStreamResponses = streamResponses
	to.DisableIpv6DNS = !ing_net.IsIPv6Enabled()
	config := &mapstructure.DecoderConfig{
		Metadata:         nil,
		WeaklyTypedInput: true,
		Result:           &to,
		TagName:          "json",
	}
	decoder, err := mapstructure.NewDecoder(config)
	if err != nil {
		glog.Warningf("unexpected error merging defaults: %v", err)
	}
	err = decoder.Decode(conf)
	if err != nil {
		glog.Warningf("unexpected error merging defaults: %v", err)
	}
	return to
}
ReadConfig obtains the configuration defined by the user merged with the defaults.
package template
import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"github.com/golang/glog"
	"github.com/mitchellh/mapstructure"
	"github.com/NCCloud/fluid/internal/ingress/controller/config"
	ing_net "github.com/NCCloud/fluid/internal/net"
	"k8s.io/apimachinery/pkg/util/sets"
)
const (
	customHTTPErrors     = "custom-http-errors"
	skipAccessLogUrls    = "skip-access-log-urls"
	whitelistSourceRange = "whitelist-source-range"
	proxyRealIPCIDR      = "proxy-real-ip-cidr"
	bindAddress          = "bind-address"
	httpRedirectCode     = "http-redirect-code"
	proxyStreamResponses = "proxy-stream-responses"
	hideHeaders          = "hide-headers"
)
var (
	validRedirectCodes = sets.NewInt([]int{301, 302, 307, 308}...)
)