feat(handler,compression): 使用 mimeutil 统一 Content-Type 检测
- 替换 mime.TypeByExtension 为 mimeutil.DetectContentType - 为 sendfile 大文件路径添加 Content-Type 设置 - 为预压缩文件添加原始 Content-Type - 添加大文件 Content-Type 测试验证 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fdab778896
commit
93e3ee0b14
@ -19,11 +19,12 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"rua.plus/lolly/internal/mimeutil"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"rua.plus/lolly/internal/cache"
|
||||
"rua.plus/lolly/internal/middleware/compression"
|
||||
@ -462,7 +463,7 @@ func (h *StaticHandler) serveFile(ctx *fasthttp.RequestCtx, filePath string, inf
|
||||
if entry.ModTime.Equal(info.ModTime()) {
|
||||
// 缓存命中且文件未修改
|
||||
ctx.Response.SetBody(entry.Data)
|
||||
ctx.Response.Header.SetContentType(mime.TypeByExtension(filepath.Ext(filePath)))
|
||||
ctx.Response.Header.SetContentType(mimeutil.DetectContentType(filePath))
|
||||
return
|
||||
}
|
||||
// 文件已修改,删除旧缓存
|
||||
@ -472,6 +473,9 @@ func (h *StaticHandler) serveFile(ctx *fasthttp.RequestCtx, filePath string, inf
|
||||
|
||||
// 大文件使用零拷贝传输
|
||||
if h.useSendfile && info.Size() >= MinSendfileSize {
|
||||
// 设置 Content-Type (sendfile 不会自动设置)
|
||||
ctx.Response.Header.SetContentType(mimeutil.DetectContentType(filePath))
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err == nil {
|
||||
defer func() { _ = file.Close() }()
|
||||
@ -495,5 +499,5 @@ func (h *StaticHandler) serveFile(ctx *fasthttp.RequestCtx, filePath string, inf
|
||||
}
|
||||
|
||||
ctx.Response.SetBody(data)
|
||||
ctx.Response.Header.SetContentType(mime.TypeByExtension(filepath.Ext(filePath)))
|
||||
ctx.Response.Header.SetContentType(mimeutil.DetectContentType(filePath))
|
||||
}
|
||||
|
||||
@ -1402,3 +1402,49 @@ func TestStaticHandler_TryFilesEdgeCases(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestStaticHandler_LargeFileContentType 测试大文件 sendfile 路径的 Content-Type
|
||||
func TestStaticHandler_LargeFileContentType(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
// 创建大于 8KB 的文件
|
||||
largeContent := make([]byte, 16*1024)
|
||||
for i := range largeContent {
|
||||
largeContent[i] = byte(i % 256)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
ext string
|
||||
expected string
|
||||
}{
|
||||
{".css", "text/css; charset=utf-8"},
|
||||
{".js", "text/javascript; charset=utf-8"},
|
||||
{".webmanifest", "application/manifest+json"},
|
||||
{".webm", "video/webm"},
|
||||
{".otf", "font/otf"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.ext, func(t *testing.T) {
|
||||
filePath := filepath.Join(tmpDir, "large"+tc.ext)
|
||||
if err := os.WriteFile(filePath, largeContent, 0644); err != nil {
|
||||
t.Fatalf("创建文件失败: %v", err)
|
||||
}
|
||||
|
||||
handler := NewStaticHandler(tmpDir, "/", nil, true) // 启用 sendfile
|
||||
ctx := &fasthttp.RequestCtx{}
|
||||
ctx.Request.SetRequestURI("/large" + tc.ext)
|
||||
|
||||
handler.Handle(ctx)
|
||||
|
||||
if got := ctx.Response.StatusCode(); got != fasthttp.StatusOK {
|
||||
t.Errorf("状态码 = %d, want %d", got, fasthttp.StatusOK)
|
||||
}
|
||||
|
||||
ct := string(ctx.Response.Header.ContentType())
|
||||
if ct != tc.expected {
|
||||
t.Errorf("Content-Type = %q, want %q", ct, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"rua.plus/lolly/internal/mimeutil"
|
||||
)
|
||||
|
||||
// GzipStatic 预压缩文件支持。
|
||||
@ -112,6 +113,10 @@ func (g *GzipStatic) ServeFile(ctx *fasthttp.RequestCtx, filePath string) bool {
|
||||
ctx.Response.Header.Set("Content-Encoding", "gzip")
|
||||
}
|
||||
ctx.Response.Header.Set("Vary", "Accept-Encoding")
|
||||
// 设置原始文件的 Content-Type
|
||||
// filePath 是原始文件路径 (如 "test.js"),直接使用即可
|
||||
ctx.Response.Header.SetContentType(mimeutil.DetectContentType(filePath))
|
||||
|
||||
fasthttp.ServeFile(ctx, fullPath)
|
||||
return true
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user