mirror of
https://github.com/alibaba/higress.git
synced 2026-03-07 18:10:54 +08:00
221 lines
6.8 KiB
Go
221 lines
6.8 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
const (
|
|
XHigressTag = "x-higress-tag"
|
|
PreHigressVersion = "pre-higress-version"
|
|
IsHtmlRequest = "is-html-request"
|
|
IsIndexRequest = "is-index-request"
|
|
EnabledGray = "enabled-gray"
|
|
)
|
|
|
|
type GrayRule struct {
|
|
Name string
|
|
GrayKeyValue []string
|
|
GrayTagKey string
|
|
GrayTagValue []string
|
|
}
|
|
|
|
type Deployment struct {
|
|
Name string
|
|
Enabled bool
|
|
Version string
|
|
BackendVersion string
|
|
Weight int
|
|
VersionPredicates map[string]string
|
|
}
|
|
|
|
type Rewrite struct {
|
|
Host string
|
|
Index map[string]string
|
|
File map[string]string
|
|
}
|
|
|
|
type Injection struct {
|
|
GlobalConfig *GlobalConfig
|
|
Head []string
|
|
Body *BodyInjection
|
|
}
|
|
|
|
type GlobalConfig struct {
|
|
Key string
|
|
FeatureKey string
|
|
Value string
|
|
Enabled bool
|
|
}
|
|
|
|
type BodyInjection struct {
|
|
First []string
|
|
Last []string
|
|
}
|
|
|
|
type GrayConfig struct {
|
|
StoreMaxAge int
|
|
GrayKey string
|
|
LocalStorageGrayKey string
|
|
GraySubKey string
|
|
Rules []*GrayRule
|
|
Rewrite *Rewrite
|
|
Html string
|
|
BaseDeployment *Deployment
|
|
GrayDeployments []*Deployment
|
|
BackendGrayTag string
|
|
UniqueGrayTag string
|
|
Injection *Injection
|
|
SkippedPaths []string
|
|
SkippedByHeaders map[string]string
|
|
IndexPaths []string
|
|
GrayWeight int
|
|
// 表示uniqueGrayTag配置项是否被用户自定义设置
|
|
UniqueGrayTagConfigured bool
|
|
}
|
|
|
|
func isValidName(s string) bool {
|
|
// 定义一个正则表达式,匹配字母、数字和下划线
|
|
re := regexp.MustCompile(`^[a-zA-Z0-9_]+$`)
|
|
return re.MatchString(s)
|
|
}
|
|
|
|
func GetWithDefault(json gjson.Result, path, defaultValue string) string {
|
|
res := json.Get(path)
|
|
if res.Exists() {
|
|
return res.String()
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func convertToStringList(results []gjson.Result) []string {
|
|
interfaces := make([]string, len(results)) // 预分配切片容量
|
|
for i, result := range results {
|
|
interfaces[i] = result.String() // 使用 String() 方法直接获取字符串
|
|
}
|
|
return interfaces
|
|
}
|
|
|
|
func compatibleConvertToStringList(results []gjson.Result, compatibleResults []gjson.Result) []string {
|
|
// 优先使用兼容模式的数据
|
|
if len(compatibleResults) == 0 {
|
|
interfaces := make([]string, len(results)) // 预分配切片容量
|
|
for i, result := range results {
|
|
interfaces[i] = result.String() // 使用 String() 方法直接获取字符串
|
|
}
|
|
return interfaces
|
|
}
|
|
compatibleInterfaces := make([]string, len(compatibleResults)) // 预分配切片容量
|
|
for i, result := range compatibleResults {
|
|
compatibleInterfaces[i] = filepath.Join(result.String(), "**")
|
|
}
|
|
return compatibleInterfaces
|
|
}
|
|
|
|
func convertToStringMap(result gjson.Result) map[string]string {
|
|
m := make(map[string]string)
|
|
result.ForEach(func(key, value gjson.Result) bool {
|
|
m[key.String()] = value.String()
|
|
return true // keep iterating
|
|
})
|
|
return m
|
|
}
|
|
|
|
func JsonToGrayConfig(json gjson.Result, grayConfig *GrayConfig) error {
|
|
// 解析 GrayKey
|
|
grayConfig.LocalStorageGrayKey = json.Get("localStorageGrayKey").String()
|
|
grayConfig.GrayKey = json.Get("grayKey").String()
|
|
if grayConfig.LocalStorageGrayKey != "" {
|
|
grayConfig.GrayKey = grayConfig.LocalStorageGrayKey
|
|
}
|
|
grayConfig.GraySubKey = json.Get("graySubKey").String()
|
|
grayConfig.BackendGrayTag = GetWithDefault(json, "backendGrayTag", "x-mse-tag")
|
|
grayConfig.UniqueGrayTag = GetWithDefault(json, "uniqueGrayTag", "x-higress-uid")
|
|
// 判断 uniqueGrayTag 是否被配置
|
|
grayConfig.UniqueGrayTagConfigured = json.Get("uniqueGrayTag").Exists()
|
|
grayConfig.StoreMaxAge = 60 * 60 * 24 * 365 // 默认一年
|
|
storeMaxAge, err := strconv.Atoi(GetWithDefault(json, "StoreMaxAge", strconv.Itoa(grayConfig.StoreMaxAge)))
|
|
if err != nil {
|
|
grayConfig.StoreMaxAge = storeMaxAge
|
|
}
|
|
|
|
grayConfig.Html = json.Get("html").String()
|
|
grayConfig.SkippedPaths = compatibleConvertToStringList(json.Get("skippedPaths").Array(), json.Get("skippedPathPrefixes").Array())
|
|
grayConfig.IndexPaths = compatibleConvertToStringList(json.Get("indexPaths").Array(), json.Get("includePathPrefixes").Array())
|
|
grayConfig.SkippedByHeaders = convertToStringMap(json.Get("skippedByHeaders"))
|
|
// 解析 Rules
|
|
rules := json.Get("rules").Array()
|
|
for _, rule := range rules {
|
|
grayRule := GrayRule{
|
|
Name: rule.Get("name").String(),
|
|
GrayKeyValue: convertToStringList(rule.Get("grayKeyValue").Array()),
|
|
GrayTagKey: rule.Get("grayTagKey").String(),
|
|
GrayTagValue: convertToStringList(rule.Get("grayTagValue").Array()),
|
|
}
|
|
grayConfig.Rules = append(grayConfig.Rules, &grayRule)
|
|
}
|
|
grayConfig.Rewrite = &Rewrite{
|
|
Host: json.Get("rewrite.host").String(),
|
|
Index: convertToStringMap(json.Get("rewrite.indexRouting")),
|
|
File: convertToStringMap(json.Get("rewrite.fileRouting")),
|
|
}
|
|
|
|
// 解析 deployment
|
|
baseDeployment := json.Get("baseDeployment")
|
|
grayDeployments := json.Get("grayDeployments").Array()
|
|
|
|
grayConfig.BaseDeployment = &Deployment{
|
|
Name: baseDeployment.Get("name").String(),
|
|
BackendVersion: baseDeployment.Get("backendVersion").String(),
|
|
Version: strings.Trim(baseDeployment.Get("version").String(), " "),
|
|
VersionPredicates: convertToStringMap(baseDeployment.Get("versionPredicates")),
|
|
}
|
|
for _, item := range grayDeployments {
|
|
if !item.Get("enabled").Bool() {
|
|
continue
|
|
}
|
|
weight := int(item.Get("weight").Int())
|
|
grayConfig.GrayDeployments = append(grayConfig.GrayDeployments, &Deployment{
|
|
Name: item.Get("name").String(),
|
|
Enabled: item.Get("enabled").Bool(),
|
|
Version: strings.Trim(item.Get("version").String(), " "),
|
|
BackendVersion: item.Get("backendVersion").String(),
|
|
Weight: weight,
|
|
VersionPredicates: convertToStringMap(item.Get("versionPredicates")),
|
|
})
|
|
if weight > 0 {
|
|
grayConfig.GrayWeight = weight
|
|
break
|
|
}
|
|
}
|
|
|
|
injectGlobalFeatureKey := GetWithDefault(json, "injection.globalConfig.featureKey", "FEATURE_STATUS")
|
|
injectGlobalKey := GetWithDefault(json, "injection.globalConfig.key", "HIGRESS_CONSOLE_CONFIG")
|
|
if !isValidName(injectGlobalFeatureKey) {
|
|
return errors.New("injection.globalConfig.featureKey is invalid")
|
|
}
|
|
if !isValidName(injectGlobalKey) {
|
|
return errors.New("injection.globalConfig.featureKey is invalid")
|
|
}
|
|
|
|
grayConfig.Injection = &Injection{
|
|
Head: convertToStringList(json.Get("injection.head").Array()),
|
|
Body: &BodyInjection{
|
|
First: convertToStringList(json.Get("injection.body.first").Array()),
|
|
Last: convertToStringList(json.Get("injection.body.last").Array()),
|
|
},
|
|
GlobalConfig: &GlobalConfig{
|
|
FeatureKey: injectGlobalFeatureKey,
|
|
Key: injectGlobalKey,
|
|
Value: json.Get("injection.globalConfig.value").String(),
|
|
Enabled: json.Get("injection.globalConfig.enabled").Bool(),
|
|
},
|
|
}
|
|
return nil
|
|
}
|