feat(cache): 开启缓存默认仅缓存标准静态资源

路由缓存策略新增 static(内置扩展名,不含 HTML)与 all;
存量 url 规范为 all。OpenResty 渲染与代理路由 UI 同步。
This commit is contained in:
ryan
2026-07-18 23:32:49 +08:00
parent 7401f5d0b4
commit 04f029c705
11 changed files with 201 additions and 29 deletions
+22 -2
View File
@@ -479,15 +479,35 @@ func renderRouteLimitBlock(limitConfig routeLimitConfig) string {
}
func renderRouteCachePolicyCondition(cacheConfig routeCacheConfig) string {
switch cacheConfig.Policy {
policy := normalizeRenderCachePolicy(cacheConfig.Policy)
switch policy {
case cachePolicyStatic:
return fmt.Sprintf(" if ($uri !~* %s) {\n set $openflare_skip_cache 1;\n }\n", quoteNginxStringLiteral(buildSuffixMatchPattern(DefaultStaticCacheExtensions)))
case cachePolicySuffix:
return fmt.Sprintf(" if ($uri !~* %s) {\n set $openflare_skip_cache 1;\n }\n", quoteNginxStringLiteral(buildSuffixMatchPattern(cacheConfig.Rules)))
case cachePolicyPathPrefix:
return fmt.Sprintf(" if ($uri !~ %s) {\n set $openflare_skip_cache 1;\n }\n", quoteNginxStringLiteral(buildPathPrefixMatchPattern(cacheConfig.Rules)))
case cachePolicyPathExact:
return fmt.Sprintf(" if ($uri !~ %s) {\n set $openflare_skip_cache 1;\n }\n", quoteNginxStringLiteral(buildPathExactMatchPattern(cacheConfig.Rules)))
default:
case cachePolicyAll, cachePolicyURL:
return ""
default:
// Unknown policy: treat as static for safety (do not cache everything).
return fmt.Sprintf(" if ($uri !~* %s) {\n set $openflare_skip_cache 1;\n }\n", quoteNginxStringLiteral(buildSuffixMatchPattern(DefaultStaticCacheExtensions)))
}
}
func normalizeRenderCachePolicy(raw string) string {
policy := strings.TrimSpace(strings.ToLower(raw))
switch policy {
case "", cachePolicyStatic:
return cachePolicyStatic
case cachePolicyURL, cachePolicyAll:
return cachePolicyAll
case cachePolicySuffix, cachePolicyPathPrefix, cachePolicyPathExact:
return policy
default:
return policy
}
}
+43
View File
@@ -398,3 +398,46 @@ func TestRenderRouteConfigPagesWithSPAFallbackServesRoot(t *testing.T) {
t.Fatalf("expected spa fallback try_files in location /, got:\n%s", routeConfig)
}
}
func TestRenderRouteCachePolicyConditionStaticDefault(t *testing.T) {
staticBlock := renderRouteCachePolicyCondition(routeCacheConfig{Enabled: true, Policy: "static"})
if staticBlock == "" {
t.Fatal("static policy should emit a path condition")
}
if !strings.Contains(staticBlock, "css") || !strings.Contains(staticBlock, "woff2") {
t.Fatalf("static policy should include default extensions, got:\n%s", staticBlock)
}
if strings.Contains(staticBlock, "html") {
t.Fatalf("static policy must not include html, got:\n%s", staticBlock)
}
emptyPolicy := renderRouteCachePolicyCondition(routeCacheConfig{Enabled: true, Policy: ""})
if emptyPolicy == "" {
t.Fatal("empty policy should default to static condition")
}
allBlock := renderRouteCachePolicyCondition(routeCacheConfig{Enabled: true, Policy: "all"})
if allBlock != "" {
t.Fatalf("all policy should not add path condition, got %q", allBlock)
}
urlBlock := renderRouteCachePolicyCondition(routeCacheConfig{Enabled: true, Policy: "url"})
if urlBlock != "" {
t.Fatalf("legacy url policy should map to all, got %q", urlBlock)
}
}
func TestRenderRouteCacheBlockIncludesStaticWhenEnabled(t *testing.T) {
block := renderRouteCacheBlock(
routeCacheConfig{Enabled: true, Policy: "static"},
ConfigSnapshot{CacheEnabled: true},
)
if !strings.Contains(block, "proxy_cache openflare_cache") {
t.Fatalf("expected proxy_cache, got:\n%s", block)
}
if !strings.Contains(block, "\\.(?:") {
t.Fatalf("expected static suffix pattern, got:\n%s", block)
}
if !strings.Contains(block, "request_method != GET") {
t.Fatalf("expected security bypass for non-GET, got:\n%s", block)
}
}
+14
View File
@@ -25,6 +25,9 @@ const (
)
const (
cachePolicyStatic = "static"
cachePolicyAll = "all"
cachePolicyURL = "url" // legacy alias of all
cachePolicySuffix = "suffix"
cachePolicyPathPrefix = "path_prefix"
cachePolicyPathExact = "path_exact"
@@ -33,6 +36,17 @@ const (
anubisAPIPrefix = "/.within.website/x/cmd/anubis/api/"
)
// DefaultStaticCacheExtensions is the built-in suffix allowlist for cache_policy=static.
// HTML is intentionally excluded (Cloudflare-like default).
var DefaultStaticCacheExtensions = []string{
"css", "js", "mjs", "map", "json",
"ico", "cur", "gif", "jpg", "jpeg", "png", "webp", "avif", "svg", "svgz",
"ttf", "otf", "woff", "woff2", "eot",
"mp3", "mp4", "webm", "ogg", "flac",
"wasm", "pdf",
"zip", "7z", "gz", "tar",
}
// OpenFlareRuntimeUser is the dedicated service account shared by the agent
// process and OpenResty worker processes.
const OpenFlareRuntimeUser = "openflare"