diff --git a/plugins/wasm-go/extensions/frontend-gray/config/config.go b/plugins/wasm-go/extensions/frontend-gray/config/config.go
index fd1c26b15..de689aad2 100644
--- a/plugins/wasm-go/extensions/frontend-gray/config/config.go
+++ b/plugins/wasm-go/extensions/frontend-gray/config/config.go
@@ -55,6 +55,7 @@ type GrayConfig struct {
GraySubKey string
Rules []*GrayRule
Rewrite *Rewrite
+ Html string
BaseDeployment *Deployment
GrayDeployments []*Deployment
BackendGrayTag string
@@ -84,6 +85,7 @@ func JsonToGrayConfig(json gjson.Result, grayConfig *GrayConfig) {
grayConfig.GraySubKey = json.Get("graySubKey").String()
grayConfig.BackendGrayTag = json.Get("backendGrayTag").String()
grayConfig.UserStickyMaxAge = json.Get("userStickyMaxAge").String()
+ grayConfig.Html = json.Get("html").String()
if grayConfig.UserStickyMaxAge == "" {
// 默认值2天
diff --git a/plugins/wasm-go/extensions/frontend-gray/envoy.yaml b/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
index e859c29a5..6dabed21d 100644
--- a/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
+++ b/plugins/wasm-go/extensions/frontend-gray/envoy.yaml
@@ -107,7 +107,8 @@ static_resources:
""
]
}
- }
+ },
+ "html": "\n \n
\napp1\n\n\n\n\t测试替换html版本\n\t
\n\t版本: {version}\n\t
\n\t\n\n"
}
- name: envoy.filters.http.router
typed_config:
@@ -116,7 +117,6 @@ static_resources:
- name: httpbin
connect_timeout: 30s
type: LOGICAL_DNS
- # Comment out the following line to test on v6 networks
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
diff --git a/plugins/wasm-go/extensions/frontend-gray/main.go b/plugins/wasm-go/extensions/frontend-gray/main.go
index 148751cc3..a6207e792 100644
--- a/plugins/wasm-go/extensions/frontend-gray/main.go
+++ b/plugins/wasm-go/extensions/frontend-gray/main.go
@@ -184,12 +184,33 @@ func onHttpResponseBody(ctx wrapper.HttpContext, grayConfig config.GrayConfig, b
isPageRequest = false // 默认值
}
frontendVersion := ctx.GetContext(config.XPreHigressTag).(string)
-
isNotFound, ok := ctx.GetContext(config.IsNotFound).(bool)
if !ok {
isNotFound = false // 默认值
}
+ // 检查是否存在自定义 HTML, 如有则省略 rewrite.indexRouting 的内容
+ if grayConfig.Html != "" {
+ log.Debugf("Returning custom HTML from config.")
+ // 替换响应体为 config.Html 内容
+ if err := proxywasm.ReplaceHttpResponseBody([]byte(grayConfig.Html)); err != nil {
+ log.Errorf("Error replacing response body: %v", err)
+ return types.ActionContinue
+ }
+
+ newHtml := util.InjectContent(grayConfig.Html, grayConfig.Injection)
+ // 替换当前html加载的动态文件版本
+ newHtml = strings.ReplaceAll(newHtml, "{version}", frontendVersion)
+
+ // 最终替换响应体
+ if err := proxywasm.ReplaceHttpResponseBody([]byte(newHtml)); err != nil {
+ log.Errorf("Error replacing injected response body: %v", err)
+ return types.ActionContinue
+ }
+
+ return types.ActionContinue
+ }
+
if isPageRequest && isNotFound && grayConfig.Rewrite.Host != "" && grayConfig.Rewrite.NotFound != "" {
client := wrapper.NewClusterClient(wrapper.RouteCluster{Host: grayConfig.Rewrite.Host})
@@ -204,30 +225,13 @@ func onHttpResponseBody(ctx wrapper.HttpContext, grayConfig config.GrayConfig, b
// 将原始字节转换为字符串
newBody := string(body)
- // 收集需要插入的内容
- headInjection := strings.Join(grayConfig.Injection.Head, "\n")
- bodyFirstInjection := strings.Join(grayConfig.Injection.Body.First, "\n")
- bodyLastInjection := strings.Join(grayConfig.Injection.Body.Last, "\n")
-
- // 使用 strings.Builder 来提高性能
- var sb strings.Builder
- // 预分配内存,避免多次内存分配
- sb.Grow(len(newBody) + len(headInjection) + len(bodyFirstInjection) + len(bodyLastInjection))
- sb.WriteString(newBody)
-
- // 进行替换
- content := sb.String()
- content = strings.ReplaceAll(content, "", fmt.Sprintf("%s\n", headInjection))
- content = strings.ReplaceAll(content, "", fmt.Sprintf("\n%s", bodyFirstInjection))
- content = strings.ReplaceAll(content, "", fmt.Sprintf("%s\n", bodyLastInjection))
-
- // 最终结果
- newBody = content
+ newBody = util.InjectContent(newBody, grayConfig.Injection)
if err := proxywasm.ReplaceHttpResponseBody([]byte(newBody)); err != nil {
return types.ActionContinue
}
}
+
return types.ActionContinue
}
diff --git a/plugins/wasm-go/extensions/frontend-gray/util/utils.go b/plugins/wasm-go/extensions/frontend-gray/util/utils.go
index a8c096816..ab7b2d475 100644
--- a/plugins/wasm-go/extensions/frontend-gray/util/utils.go
+++ b/plugins/wasm-go/extensions/frontend-gray/util/utils.go
@@ -278,3 +278,28 @@ func FilterGrayWeight(grayConfig *config.GrayConfig, preVersion string, preUniqu
}
return nil
}
+
+// InjectContent 用于将内容注入到 HTML 文档的指定位置
+func InjectContent(originalHtml string, injectionConfig *config.Injection) string {
+
+ headInjection := strings.Join(injectionConfig.Head, "\n")
+ bodyFirstInjection := strings.Join(injectionConfig.Body.First, "\n")
+ bodyLastInjection := strings.Join(injectionConfig.Body.Last, "\n")
+
+ // 使用 strings.Builder 来提高性能
+ var sb strings.Builder
+ // 预分配内存,避免多次内存分配
+ sb.Grow(len(originalHtml) + len(headInjection) + len(bodyFirstInjection) + len(bodyLastInjection))
+ sb.WriteString(originalHtml)
+
+ modifiedHtml := sb.String()
+
+ // 注入到头部
+ modifiedHtml = strings.ReplaceAll(modifiedHtml, "", headInjection + "\n")
+ // 注入到body头
+ modifiedHtml = strings.ReplaceAll(modifiedHtml, "", "\n" + bodyFirstInjection)
+ // 注入到body尾
+ modifiedHtml = strings.ReplaceAll(modifiedHtml, "", bodyLastInjection + "\n")
+
+ return modifiedHtml
+}
diff --git a/plugins/wasm-go/extensions/frontend-gray/util/utils_test.go b/plugins/wasm-go/extensions/frontend-gray/util/utils_test.go
index 7ba014225..d51e17f32 100644
--- a/plugins/wasm-go/extensions/frontend-gray/util/utils_test.go
+++ b/plugins/wasm-go/extensions/frontend-gray/util/utils_test.go
@@ -122,3 +122,22 @@ func TestFilterGrayWeight(t *testing.T) {
})
}
}
+
+func TestReplaceHtml(t *testing.T) {
+ var tests = []struct {
+ name string
+ input string
+ }{
+ {"demo", `{"injection":{"head":[""],"body":{"first":[""],"last":[""]},"last":[""]},"html": "\n \n\napp1\n\n\n\n\t测试替换html版本\n\t
\n\t版本: {version}\n\t
\n\t\n\n"}`},
+ {"demo-noBody", `{"injection":{"head":[""],"body":{"first":[""],"last":[""]},"last":[""]},"html": "\n \n\napp1\n\n\n"}`},
+ }
+ for _, test := range tests {
+ testName := test.name
+ t.Run(testName, func(t *testing.T) {
+ grayConfig := &config.GrayConfig{}
+ config.JsonToGrayConfig(gjson.Parse(test.input), grayConfig)
+ result := InjectContent(grayConfig.Html, grayConfig.Injection)
+ t.Logf("result-----: %v", result)
+ })
+ }
+}