Skip to content

feat: Add response-cache plugin #3061

Merged
johnlanni merged 7 commits intoalibaba:mainfrom
Jing-ze:add-reponse-cache
Dec 26, 2025
Merged

feat: Add response-cache plugin #3061
johnlanni merged 7 commits intoalibaba:mainfrom
Jing-ze:add-reponse-cache

Conversation

@Jing-ze
Copy link
Collaborator

@Jing-ze Jing-ze commented Oct 28, 2025

Ⅰ. Describe what this PR did

This PR fixes issues in the response-cache plugin implementation #2025 and adds comprehensive unit tests:

Bug Fixes:

  • Fixed cache key extraction logic when cacheKeyFromHeader or cacheKeyFromBody is empty - now properly skips response processing instead of unnecessarily buffering response bodies
  • Removed redundant log parameter from cache provider functions to fix interface mismatch
  • Fixed trailing whitespace in config validation
  • Updated deprecated API usage (wrapper.ParseConfigBywrapper.ParseConfig, etc.)

Improvements:

  • Updated Go module dependencies to latest versions
  • Enhanced documentation (README and README_EN) with clarifications about cache key extraction behavior
  • Added proper MIME type handling (consistently use "application/json" instead of "json")

Testing:

  • Added comprehensive unit tests (main_test.go) covering:

Ⅱ. Does this pull request fix one issue?

No specific issue, but fixes critical bugs in PR #2025.

Ⅲ. Why don't you add test cases (unit test/integration test)?

Comprehensive unit tests have been added.

The test suite includes:

  • TestParseConfig: Tests configuration validation for various scenarios (header key, body key, conflicts, missing cache provider)
  • TestOnHttpRequestHeaders: Tests request header processing for different content types
  • TestOnHttpRequestBody: Tests body parsing and key extraction
  • TestOnHttpResponseHeaders: Tests response header processing
  • TestOnHttpResponseBody: Tests response body extraction
  • TestCacheHitFlow: Tests complete cache hit/miss flows with Redis mocking

All tests use proper Redis response mocking via the test framework utilities.

Ⅳ. Describe how to verify it

Run unit tests:

cd plugins/wasm-go/extensions/response-cache
go test ./... -v

Expected test results:

  • All test cases should pass
  • Tests demonstrate proper cache key extraction from headers and bodies
  • Tests verify correct handling of cache hits and misses
  • Tests ensure skip cache behavior works correctly

Ⅴ. Special notes for reviews

This PR addresses several critical issues from the original PR #2025:

  • Resource waste bug: When cache key extraction failed, the plugin would unnecessarily buffer request/response bodies

The changes maintain backward compatibility while fixing these issues and adding robust test coverage.

mirror58229 and others added 3 commits October 27, 2025 18:47
…update Go module version, and enhance README documentation. Add comprehensive tests for cache key extraction from headers and bodies, ensuring proper handling of various configurations.

Change-Id: I3c6ee39de0211533931afec3f559603aa7407ecf
Co-developed-by: Cursor <noreply@cursor.com>
@lingma-agents
Copy link

lingma-agents bot commented Oct 28, 2025

新增响应缓存插件功能及完善测试覆盖

变更概述
  • 新功能

    • 实现了通用响应缓存插件,支持从请求头或请求体提取缓存键,从响应体提取缓存值并存储。
    • 支持 Redis 作为缓存后端,包括连接配置、认证、超时和缓存过期时间设置。
    • 插件支持跳过缓存的请求头 x-higress-skip-response-cache: on,以及缓存状态响应头 x-cache-status 的返回(hit/miss/skip)。
    • 支持从 JSON 响应体中使用 GJSON PATH 语法提取缓存键和值。
    • 提供完整的插件配置解析、验证和初始化逻辑。
  • 测试更新

    • 添加了全面的单元测试,覆盖配置解析、请求头处理、请求体处理、响应头处理、响应体处理等多个阶段。
    • 包含对缓存命中和未命中流程的模拟测试,使用 Redis 响应模拟工具验证缓存行为。
    • 测试用例覆盖了多种配置场景,如 header 提取键、body 提取键、body 作为键、配置冲突、最小配置等。
  • 文档

    • 添加了中文和英文的插件配置参考文档(README.md 和 README_EN.md),详细说明插件功能、配置项、使用示例和常见问题。
    • 文档中包含了基础配置、响应体作为缓存值、请求体作为缓存键等示例,以及 GJSON PATH 语法的进阶用法。
  • 依赖更新

    • 更新了 Go 模块依赖,使用了较新的 github.com/higress-group/wasm-gogithub.com/higress-group/proxy-wasm-go-sdk 版本。
    • 添加了 github.com/tidwall/gjsongithub.com/tidwall/resp 作为处理 JSON 和 Redis 响应的依赖。
  • 重构

    • 将缓存逻辑封装到 cache 包中,定义了 Provider 接口和 ProviderConfig 结构体,提高了代码的模块化和可扩展性。
    • 将插件配置解析和验证逻辑封装到 config 包中,使 main.go 更专注于处理 HTTP 请求和响应的逻辑。
变更文件
文件路径 变更说明
plugins/​wasm-go/​extensions/​response-cache/​README.​md 新增中文 README 文件,详细介绍了响应缓存插件的功能、配置项、使用示例和常见问题。
plugins/​wasm-go/​extensions/​response-cache/​README_​EN.​md 新增英文 README 文件,详细介绍了响应缓存插件的功能、配置项、使用示例和常见问题。
plugins/​wasm-go/​extensions/​response-cache/​cache/​provider.​go 新增缓存提供者接口和配置结构体,定义了缓存提供者的验证和创建逻辑,并支持从 JSON 配置中解析缓存配置。
plugins/​wasm-go/​extensions/​response-cache/​cache/​redis.​go 新增 Redis 缓存提供者的实现,包括连接初始化、Get 和 Set 操作,以及缓存键前缀的获取。
plugins/​wasm-go/​extensions/​response-cache/​config/​config.​go 新增插件配置结构体和解析逻辑,支持从 JSON 配置中解析缓存提供者配置、缓存键/值提取规则和响应状态码列表,并进行验证。
plugins/​wasm-go/​extensions/​response-cache/​core.​go 新增核心缓存逻辑,包括检查缓存键、处理缓存响应、处理缓存命中和未命中、缓存响应值等函数。
plugins/​wasm-go/​extensions/​response-cache/​go.​mod 新增 Go 模块文件,定义了插件的模块路径和依赖。
plugins/​wasm-go/​extensions/​response-cache/​go.​sum 新增 Go 依赖校验和文件。
plugins/​wasm-go/​extensions/​response-cache/​main.​go 新增插件主文件,实现了 OnHttpRequestHeaders、OnHttpRequestBody、OnHttpResponseHeaders 和 OnHttpResponseBody 四个回调函数,处理 HTTP 请求和响应的缓存逻辑。
plugins/​wasm-go/​extensions/​response-cache/​main_​test.​go 新增插件单元测试文件,覆盖了配置解析、请求头处理、请求体处理、响应头处理、响应体处理等多个阶段的测试用例。

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

@codecov-commenter
Copy link

codecov-commenter commented Oct 28, 2025

Codecov Report

❌ Patch coverage is 72.56318% with 76 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.16%. Comparing base (810ef8f) to head (c28f885).

Files with missing lines Patch % Lines
plugins/wasm-go/extensions/response-cache/main.go 80.86% 15 Missing and 7 partials ⚠️
...asm-go/extensions/response-cache/cache/provider.go 57.14% 8 Missing and 10 partials ⚠️
plugins/wasm-go/extensions/response-cache/core.go 63.26% 13 Missing and 5 partials ⚠️
...wasm-go/extensions/response-cache/config/config.go 75.00% 7 Missing and 3 partials ⚠️
...s/wasm-go/extensions/response-cache/cache/redis.go 74.19% 5 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3061      +/-   ##
==========================================
+ Coverage   43.42%   44.16%   +0.73%     
==========================================
  Files          82       87       +5     
  Lines       10922    11199     +277     
==========================================
+ Hits         4743     4946     +203     
- Misses       5850     5897      +47     
- Partials      329      356      +27     
Flag Coverage Δ
wasm-go-plugin-response-cache 72.56% <72.56%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...s/wasm-go/extensions/response-cache/cache/redis.go 74.19% <74.19%> (ø)
...wasm-go/extensions/response-cache/config/config.go 75.00% <75.00%> (ø)
...asm-go/extensions/response-cache/cache/provider.go 57.14% <57.14%> (ø)
plugins/wasm-go/extensions/response-cache/core.go 63.26% <63.26%> (ø)
plugins/wasm-go/extensions/response-cache/main.go 80.86% <80.86%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@lingma-agents lingma-agents bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 代码评审报告

🎯 评审意见概览
严重度 数量 说明
🔴 Blocker 0 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。
🟠 Critical 1 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。
🟡 Major 3 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。
🟢 Minor 1 次要问题,酬情优化。例如:代码格式不规范或注释缺失。

总计: 5 个问题

📋 评审意见详情
💡 代码实现建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
🔹 plugins/wasm-go/extensions/response-cache/cache/provider.go (2 💬)
🔹 plugins/wasm-go/extensions/response-cache/cache/redis.go (1 💬)
🔹 plugins/wasm-go/extensions/response-cache/config/config.go (1 💬)
🔹 plugins/wasm-go/extensions/response-cache/core.go (1 💬)
🚀 架构设计建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍1. 架构一致性问题:缓存提供者初始化逻辑分散

当前缓存提供者的初始化逻辑分散在多个文件中,例如在 provider.go 中定义了接口和初始化逻辑,而在 redis.go 中实现了具体的初始化。这种分散可能导致未来新增缓存类型时维护成本增加。建议将初始化逻辑集中到一个统一的工厂类或初始化管理器中,以提高代码的可维护性和扩展性。

⚠️ 潜在风险

未来新增缓存类型时,可能需要修改多个文件,增加出错风险和维护成本。

🔍2. 跨文件问题:配置解析逻辑重复

provider.goconfig.go 中都存在对配置项的解析逻辑,尤其是对默认值的处理。这种重复可能导致配置解析不一致,增加调试和维护难度。建议将配置解析逻辑统一到一个地方,避免重复代码。

📌 关键代码

func (c *ProviderConfig) FromJson(json gjson.Result) {
	c.typ = json.Get("type").String()
	c.serviceName = json.Get("serviceName").String()
	c.servicePort = int(json.Get("servicePort").Int())
	if !json.Get("servicePort").Exists() {
		if strings.HasSuffix(c.serviceName, ".static") {
			// use default logic port which is 80 for static service
			c.servicePort = 80
		} else {
			c.servicePort = 6379
		}
	}
	c.serviceHost = json.Get("serviceHost").String()
	c.username = json.Get("username").String()
	if !json.Get("username").Exists() {
		c.username = ""
	}
	c.password = json.Get("password").String()
	if !json.Get("password").Exists() {
		c.password = ""
	}
	c.timeout = uint32(json.Get("timeout").Int())
	if !json.Get("timeout").Exists() {
		c.timeout = 10000
	}
	c.cacheTTL = int(json.Get("cacheTTL").Int())
	if !json.Get("cacheTTL").Exists() {
		c.cacheTTL = 0
		// c.cacheTTL = 3600000
	}
	if json.Get("cacheKeyPrefix").Exists() {
		c.cacheKeyPrefix = json.Get("cacheKeyPrefix").String()
	} else {
		c.cacheKeyPrefix = DEFAULT_CACHE_PREFIX
	}
}
func (c *PluginConfig) FromJson(json gjson.Result) {
	c.cacheProviderConfig.FromJson(json.Get("cache"))
	c.CacheKeyFromHeader = json.Get("cacheKeyFromHeader").String()
	c.CacheKeyFromBody = json.Get("cacheKeyFromBody").String()

	c.CacheValueFromBodyType = json.Get("cacheValueFromBodyType").String()
	if c.CacheValueFromBodyType == "" {
		c.CacheValueFromBodyType = "application/json"
	}

	c.CacheValueFromBody = json.Get("cacheValueFromBody").String()

	cacheResponseCode := json.Get("cacheResponseCode").Array()
	c.CacheResponseCode = make([]int32, 0, len(cacheResponseCode))
	for _, v := range cacheResponseCode {
		responseCode, err := strconv.Atoi(v.String())
		if err != nil || responseCode < 100 || responseCode > 999 {
			log.Errorf("Skip invalid response_code value: %s", v.String())
			return
		}
		c.CacheResponseCode = append(c.CacheResponseCode, int32(responseCode))
	}

	if len(c.CacheResponseCode) == 0 {
		c.CacheResponseCode = []int32{200}
	}
}

⚠️ 潜在风险

配置解析不一致可能导致缓存功能异常,增加调试和维护难度。

🔍3. 技术债务:错误处理不一致

在多个文件中,错误处理的方式不一致。例如,在 redis.go 中,Redis客户端初始化失败时未向上传播错误,而在其他地方则有错误传播。这种不一致可能导致错误处理不完整,影响系统的健壮性。建议统一错误处理机制,确保所有错误都能被正确处理和传播。

📌 关键代码

func (rp *redisProvider) Init(username string, password string, timeout uint32) error {
	err := rp.client.Init(rp.config.username, rp.config.password, int64(rp.config.timeout))
	if rp.client.Ready() {
		log.Info("redis init successfully")
	} else {
		log.Error("redis init failed, will try later")
	}
	return err
}

⚠️ 潜在风险

错误处理不一致可能导致系统在遇到错误时行为不可预测,影响系统的稳定性和可靠性。

🔍4. 性能影响:缓存键生成逻辑可能成为瓶颈

core.go 中,缓存键的生成逻辑涉及字符串拼接和多次调用。如果请求量大,这种操作可能成为性能瓶颈。建议优化缓存键生成逻辑,减少不必要的字符串操作,提高性能。

📌 关键代码

queryKey := activeCacheProvider.GetCacheKeyPrefix() + key

⚠️ 潜在风险

在高并发场景下,缓存键生成逻辑可能成为性能瓶颈,影响系统响应速度。

🔍5. 安全风险:缓存键和值的处理缺乏安全校验

core.gomain.go 中,缓存键和值的处理缺乏安全校验,可能存在注入攻击的风险。建议对缓存键和值进行严格的校验和过滤,防止恶意输入导致的安全问题。

📌 关键代码

queryKey := activeCacheProvider.GetCacheKeyPrefix() + key
key = bodyJson.Get(c.CacheKeyFromBody).String()

⚠️ 潜在风险

缺乏安全校验可能导致缓存键和值被恶意利用,引发安全问题。

审查详情
📒 文件清单 (11 个文件)
新增: 11 个文件

✅ 新增文件:

  • plugins/wasm-go/extensions/response-cache/README.md
  • plugins/wasm-go/extensions/response-cache/README_EN.md
  • plugins/wasm-go/extensions/response-cache/cache/provider.go
  • plugins/wasm-go/extensions/response-cache/cache/redis.go
  • plugins/wasm-go/extensions/response-cache/config/config.go
  • plugins/wasm-go/extensions/response-cache/core.go
  • plugins/wasm-go/extensions/response-cache/go.mod
  • plugins/wasm-go/extensions/response-cache/go.sum
  • plugins/wasm-go/extensions/response-cache/main.go
  • plugins/wasm-go/extensions/response-cache/main_test.go
  • plugins/wasm-go/extensions/response-cache/option.yaml

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

… key construction, streamline cache key usage in CheckCacheForKey and cacheResponse functions, and clean up unused username and password checks in ProviderConfig.

Change-Id: I784f4811ee3f38a4f58db37b07075c545366763c
Co-developed-by: Cursor <noreply@cursor.com>
@Jing-ze
Copy link
Collaborator Author

Jing-ze commented Oct 28, 2025

@CH3CHO 请查看一下最新的两次commit是否修复了上一个PR里提的问题 #2025


@CH3CHO Please check whether the latest two commits have fixed the problems mentioned in the previous PR #2025

Copy link
Collaborator

@johnlanni johnlanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@johnlanni johnlanni merged commit 38d50bb into alibaba:main Dec 26, 2025
15 checks passed
daixijun pushed a commit to daixijun/higress that referenced this pull request Jan 13, 2026
Co-authored-by: mirror58229 <674958229@qq.com>
ISADBA pushed a commit to ISADBA/higress that referenced this pull request Jan 13, 2026
Co-authored-by: mirror58229 <674958229@qq.com>
ISADBA pushed a commit to ISADBA/higress that referenced this pull request Jan 13, 2026
Co-authored-by: mirror58229 <674958229@qq.com>
Jing-ze added a commit that referenced this pull request Jan 19, 2026
Co-authored-by: mirror58229 <674958229@qq.com>
johnlanni pushed a commit that referenced this pull request Jan 31, 2026
Co-authored-by: mirror58229 <674958229@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants