fix(cache): 存量空/url 策略规范为 all,避免静默收窄

评审修复:enabled 且 policy 为空或 url 时,写入/展示/快照/渲染均映射为 all,
保证旧站点宽缓存范围不变;新建 UI 仍显式提交 static 作为推荐默认。
This commit is contained in:
ryan
2026-07-19 00:02:52 +08:00
parent 04f029c705
commit 204f6d9a8b
11 changed files with 113 additions and 38 deletions
@@ -347,10 +347,35 @@ func normalizeSnapshotRoutes(routes []snapshotRoute) []snapshotRoute {
routes[index].BasicAuthPassword = ""
}
routes[index].UpstreamType = normalizeUpstreamType(routes[index].UpstreamType)
routes[index].CachePolicy = normalizeSnapshotCachePolicy(
routes[index].CacheEnabled,
routes[index].CachePolicy,
)
if !routes[index].CacheEnabled {
routes[index].CacheRules = nil
}
}
return routes
}
// normalizeSnapshotCachePolicy aligns published policy with edge-cache-design:
// legacy empty/url → all; disabled → empty; static/suffix/... kept.
func normalizeSnapshotCachePolicy(enabled bool, raw string) string {
if !enabled {
return ""
}
policy := strings.TrimSpace(strings.ToLower(raw))
switch policy {
case "", "url", "all":
return "all"
case "static", "suffix", "path_prefix", "path_exact":
return policy
default:
// Unknown: prefer static over caching everything.
return "static"
}
}
func flattenSnapshotRoutesBySite(routes []snapshotRoute) map[string]snapshotRoute {
siteMap := make(map[string]snapshotRoute)
for _, route := range normalizeSnapshotRoutes(routes) {
+15 -4
View File
@@ -436,17 +436,20 @@ func decodeStoredCustomHeaders(raw string) ([]CustomHeaderInput, error) {
return normalizeCustomHeaders(headers)
}
// normalizeCachePolicy stores API write values.
// When enabling with empty/url policy, keep legacy "all" semantics so old rows
// and clients that omit policy do not silently narrow cache to static extensions.
// New UI should send policy=static explicitly when choosing the recommended default.
func normalizeCachePolicy(enabled bool, raw string) string {
if !enabled {
return ""
}
policy := strings.TrimSpace(strings.ToLower(raw))
switch policy {
case "", proxyRouteCachePolicyStatic:
return proxyRouteCachePolicyStatic
case proxyRouteCachePolicyURL, proxyRouteCachePolicyAll:
// Legacy url is normalized to all (full GET allow after security bypass).
case "", proxyRouteCachePolicyURL, proxyRouteCachePolicyAll:
return proxyRouteCachePolicyAll
case proxyRouteCachePolicyStatic:
return proxyRouteCachePolicyStatic
case proxyRouteCachePolicySuffix, proxyRouteCachePolicyPathPrefix, proxyRouteCachePolicyPathExact:
return policy
default:
@@ -454,6 +457,14 @@ func normalizeCachePolicy(enabled bool, raw string) string {
}
}
// displayCachePolicy normalizes values for API list/get (and UI).
func displayCachePolicy(enabled bool, raw string) string {
if !enabled {
return ""
}
return normalizeCachePolicy(true, raw)
}
func normalizeCacheRules(enabled bool, rawPolicy string, rules []string) ([]string, error) {
if !enabled {
return []string{}, nil
@@ -309,7 +309,7 @@ func buildProxyRouteView(ctx context.Context, route *model.ProxyRoute) (*View, e
LimitConnPerIP: route.LimitConnPerIP,
LimitRate: route.LimitRate,
CacheEnabled: route.CacheEnabled,
CachePolicy: route.CachePolicy,
CachePolicy: displayCachePolicy(route.CacheEnabled, route.CachePolicy),
CacheRules: route.CacheRules,
CacheRuleList: cacheRules,
CustomHeaders: route.CustomHeaders,
@@ -83,12 +83,18 @@ func TestCreateProxyRouteHTTPSRequiresCoveringCertificate(t *testing.T) {
func TestNormalizeCachePolicyDefaultsAndLegacy(t *testing.T) {
assert.Equal(t, "", normalizeCachePolicy(false, "static"))
assert.Equal(t, proxyRouteCachePolicyStatic, normalizeCachePolicy(true, ""))
// Empty/url on write = legacy all (compat); UI sends static explicitly for new default.
assert.Equal(t, proxyRouteCachePolicyAll, normalizeCachePolicy(true, ""))
assert.Equal(t, proxyRouteCachePolicyStatic, normalizeCachePolicy(true, "static"))
assert.Equal(t, proxyRouteCachePolicyAll, normalizeCachePolicy(true, "url"))
assert.Equal(t, proxyRouteCachePolicyAll, normalizeCachePolicy(true, "all"))
assert.Equal(t, proxyRouteCachePolicySuffix, normalizeCachePolicy(true, "suffix"))
assert.Equal(t, "", displayCachePolicy(false, "all"))
assert.Equal(t, proxyRouteCachePolicyAll, displayCachePolicy(true, ""))
assert.Equal(t, proxyRouteCachePolicyAll, displayCachePolicy(true, "url"))
assert.Equal(t, proxyRouteCachePolicyStatic, displayCachePolicy(true, "static"))
rules, err := normalizeCacheRules(true, "url", []string{"css"})
require.NoError(t, err)
assert.Empty(t, rules)