From 2bdc8f3b3b3cfa66fbd9e988326f5e197c7e2d14 Mon Sep 17 00:00:00 2001 From: xfy Date: Wed, 22 Apr 2026 13:35:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor(handler,middleware,server):=20?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E9=A2=84=E5=8E=8B=E7=BC=A9=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E7=81=B5=E6=B4=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - NewGzipStatic 增加 precompressedExtensions 参数,支持自定义预压缩扩展名 - SetGzipStatic 分离源文件扩展名和预压缩扩展名参数 - 更新相关测试用例 Co-Authored-By: Claude Opus 4.7 --- internal/handler/static.go | 11 ++++---- internal/handler/static_test.go | 6 ++-- .../middleware/compression/gzip_static.go | 10 +++++-- .../compression/gzip_static_test.go | 28 +++++++++---------- internal/server/server.go | 8 ++++-- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/internal/handler/static.go b/internal/handler/static.go index 9c6c87f..d9f4cec 100644 --- a/internal/handler/static.go +++ b/internal/handler/static.go @@ -164,18 +164,19 @@ func (h *StaticHandler) SetFileCache(fc *cache.FileCache) { // SetGzipStatic 设置预压缩文件支持。 // -// 启用后,对于匹配扩展名的请求,优先发送 .gz 预压缩文件。 +// 启用后,对于匹配扩展名的请求,优先发送预压缩文件。 // // 参数: // - enabled: 是否启用预压缩支持 -// - extensions: 需要支持预压缩的文件扩展名列表(如 [".html", ".css", ".js"]) +// - extensions: 支持预压缩的源文件扩展名列表(如 [".html", ".css", ".js"]),为空使用默认值 +// - precompressedExtensions: 预压缩文件扩展名列表(如 [".br", ".gz"]),为空使用默认值 // // 使用示例: // -// handler.SetGzipStatic(true, []string{".html", ".css", ".js"}) -func (h *StaticHandler) SetGzipStatic(enabled bool, extensions []string) { +// handler.SetGzipStatic(true, nil, []string{".gz", ".br"}) +func (h *StaticHandler) SetGzipStatic(enabled bool, extensions, precompressedExtensions []string) { if enabled { - h.gzipStatic = compression.NewGzipStatic(true, h.root, extensions) + h.gzipStatic = compression.NewGzipStatic(true, h.root, extensions, precompressedExtensions) } } diff --git a/internal/handler/static_test.go b/internal/handler/static_test.go index 7608811..bc5818d 100644 --- a/internal/handler/static_test.go +++ b/internal/handler/static_test.go @@ -449,13 +449,13 @@ func TestStaticHandler_SetGzipStatic(t *testing.T) { handler := NewStaticHandler("/var/www", "/", nil, false) // 启用 gzip - handler.SetGzipStatic(true, []string{".gz", ".gzip"}) + handler.SetGzipStatic(true, nil, []string{".gz", ".gzip"}) if handler.gzipStatic == nil { t.Error("Expected gzipStatic to be non-nil") } // 禁用 gzip - handler.SetGzipStatic(false, nil) + handler.SetGzipStatic(false, nil, nil) // gzipStatic 保持不变(SetGzipStatic 只在 enabled=true 时设置) } @@ -525,7 +525,7 @@ func TestStaticHandler_Handle_Precompressed(t *testing.T) { } handler := NewStaticHandler(tmpDir, "/", nil, false) - handler.SetGzipStatic(true, []string{".gz"}) + handler.SetGzipStatic(true, nil, []string{".gz"}) ctx := &fasthttp.RequestCtx{} ctx.Request.SetRequestURI("/test.txt") diff --git a/internal/middleware/compression/gzip_static.go b/internal/middleware/compression/gzip_static.go index 8ebc7b2..fc0d02b 100644 --- a/internal/middleware/compression/gzip_static.go +++ b/internal/middleware/compression/gzip_static.go @@ -55,19 +55,23 @@ type GzipStatic struct { // 参数: // - enabled: 是否启用预压缩支持 // - root: 静态文件根目录路径 -// - extensions: 支持预压缩的文件扩展名列表,为空则使用默认值 +// - extensions: 支持预压缩的源文件扩展名列表(如 .html, .css),为空则使用默认值 +// - precompressedExtensions: 预压缩文件扩展名列表(如 .br, .gz),为空则使用默认值 // // 返回值: // - *GzipStatic: 创建的预压缩文件处理器 -func NewGzipStatic(enabled bool, root string, extensions []string) *GzipStatic { +func NewGzipStatic(enabled bool, root string, extensions, precompressedExtensions []string) *GzipStatic { if len(extensions) == 0 { extensions = []string{".html", ".css", ".js", ".json", ".xml", ".svg", ".txt"} } + if len(precompressedExtensions) == 0 { + precompressedExtensions = []string{".br", ".gz"} + } return &GzipStatic{ enabled: enabled, root: root, extensions: extensions, - precompressedExtensions: []string{".br", ".gz"}, + precompressedExtensions: precompressedExtensions, } } diff --git a/internal/middleware/compression/gzip_static_test.go b/internal/middleware/compression/gzip_static_test.go index da142ed..4d27f4f 100644 --- a/internal/middleware/compression/gzip_static_test.go +++ b/internal/middleware/compression/gzip_static_test.go @@ -35,7 +35,7 @@ func TestGzipStaticServeFile_BrotliPriority(t *testing.T) { t.Fatalf("创建 .gz 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) tests := []struct { acceptEncoding string @@ -119,7 +119,7 @@ func TestGzipStaticServeFile_GzipFallback(t *testing.T) { t.Fatalf("创建 .gz 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) tests := []struct { acceptEncoding string @@ -177,7 +177,7 @@ func TestGzipStaticServeFile_AcceptEncodingParsing(t *testing.T) { t.Fatalf("创建 .br 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) tests := []struct { name string @@ -241,7 +241,7 @@ func TestGzipStaticServeFile_Disabled(t *testing.T) { } // 禁用的 GzipStatic - g := NewGzipStatic(false, tmpDir, nil) + g := NewGzipStatic(false, tmpDir, nil, nil) ctx := &fasthttp.RequestCtx{} ctx.Request.Header.Set("Accept-Encoding", "br") @@ -263,7 +263,7 @@ func TestGzipStaticServeFile_InvalidExtension(t *testing.T) { t.Fatalf("创建 .br 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) ctx := &fasthttp.RequestCtx{} ctx.Request.Header.Set("Accept-Encoding", "br") @@ -285,7 +285,7 @@ func TestGzipStaticServeFile_PathTraversal(t *testing.T) { t.Fatalf("创建 .br 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) ctx := &fasthttp.RequestCtx{} ctx.Request.Header.Set("Accept-Encoding", "br") @@ -308,7 +308,7 @@ func TestGzipStaticServeFile_VaryHeader(t *testing.T) { t.Fatalf("创建 .br 文件失败: %v", err) } - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) ctx := &fasthttp.RequestCtx{} ctx.Request.Header.Set("Accept-Encoding", "br") @@ -323,7 +323,7 @@ func TestGzipStaticServeFile_VaryHeader(t *testing.T) { // TestNewGzipStatic_DefaultExtensions 测试默认扩展名 func TestNewGzipStatic_DefaultExtensions(t *testing.T) { - g := NewGzipStatic(true, "/tmp", nil) + g := NewGzipStatic(true, "/tmp", nil, nil) expected := []string{".html", ".css", ".js", ".json", ".xml", ".svg", ".txt"} got := g.Extensions() @@ -342,7 +342,7 @@ func TestNewGzipStatic_DefaultExtensions(t *testing.T) { // TestNewGzipStatic_CustomExtensions 测试自定义扩展名 func TestNewGzipStatic_CustomExtensions(t *testing.T) { custom := []string{".custom", ".ext"} - g := NewGzipStatic(true, "/tmp", custom) + g := NewGzipStatic(true, "/tmp", custom, nil) got := g.Extensions() if len(got) != 2 || got[0] != ".custom" || got[1] != ".ext" { @@ -352,12 +352,12 @@ func TestNewGzipStatic_CustomExtensions(t *testing.T) { // TestGzipStatic_Enabled 测试 Enabled 方法 func TestGzipStatic_Enabled(t *testing.T) { - g1 := NewGzipStatic(true, "/tmp", nil) + g1 := NewGzipStatic(true, "/tmp", nil, nil) if !g1.Enabled() { t.Error("Enabled() = false, want true") } - g2 := NewGzipStatic(false, "/tmp", nil) + g2 := NewGzipStatic(false, "/tmp", nil, nil) if g2.Enabled() { t.Error("Enabled() = true, want false") } @@ -366,7 +366,7 @@ func TestGzipStatic_Enabled(t *testing.T) { // TestDefaultExtensions 测试默认扩展名(通过 NewGzipStatic 间接测试) func TestDefaultExtensions(t *testing.T) { expected := []string{".html", ".css", ".js", ".json", ".xml", ".svg", ".txt"} - g := NewGzipStatic(true, "/tmp", nil) + g := NewGzipStatic(true, "/tmp", nil, nil) got := g.Extensions() if len(got) != len(expected) { @@ -462,7 +462,7 @@ func TestTryServeFile(t *testing.T) { ctx := &fasthttp.RequestCtx{} ctx.Request.Header.Set("Accept-Encoding", "br") - g := NewGzipStatic(true, tmpDir, nil) + g := NewGzipStatic(true, tmpDir, nil, nil) served := g.ServeFile(ctx, "test.js") if !served { @@ -477,7 +477,7 @@ func TestTryServeFile(t *testing.T) { // TestGzipStatic_PrecompressedExtensions 测试预压缩扩展名优先级 func TestGzipStatic_PrecompressedExtensions(t *testing.T) { - g := NewGzipStatic(true, "/tmp", nil) + g := NewGzipStatic(true, "/tmp", nil, nil) // 验证默认预压缩扩展名顺序 expected := []string{".br", ".gz"} diff --git a/internal/server/server.go b/internal/server/server.go index d3439a3..ef1b5ab 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -1083,7 +1083,9 @@ func (s *Server) registerStaticHandlersWithLocationEngine(cfg *config.ServerConf staticHandler.SetCacheTTL(5 * time.Second) } if cfg.Compression.GzipStatic { - staticHandler.SetGzipStatic(true, cfg.Compression.GzipStaticExtensions) + // extensions: 源文件类型,为空使用默认值 + // GzipStaticExtensions: 预压缩文件扩展名(如 .br, .gz) + staticHandler.SetGzipStatic(true, nil, cfg.Compression.GzipStaticExtensions) } // 设置符号链接安全检查 @@ -1446,7 +1448,9 @@ func (s *Server) registerStaticHandlers(router *handler.Router, cfg *config.Serv staticHandler.SetCacheTTL(5 * time.Second) } if cfg.Compression.GzipStatic { - staticHandler.SetGzipStatic(true, cfg.Compression.GzipStaticExtensions) + // extensions: 源文件类型,为空使用默认值 + // GzipStaticExtensions: 预压缩文件扩展名(如 .br, .gz) + staticHandler.SetGzipStatic(true, nil, cfg.Compression.GzipStaticExtensions) } // 设置符号链接安全检查