perf(handler): add FileInfo cache to handleTryFiles and handleInternalRedirect

- Check fileInfoCache before os.Stat in handleTryFiles
- Check fileInfoCache before os.Stat in handleInternalRedirect
- Reduces system calls for try_files scenarios

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-04-30 15:56:42 +08:00
parent 3b608be0de
commit 73ef3a938b

View File

@ -396,16 +396,47 @@ func (h *StaticHandler) handleTryFiles(ctx *fasthttp.RequestCtx, reqPath string)
}
// 检查文件/目录是否存在
info, err := os.Stat(filePath)
if err != nil {
continue // 不存在,尝试下一个
// 先查 FileInfo 缓存
var info os.FileInfo
var err error
if h.fileInfoCache != nil {
if cachedInfo, ok := h.fileInfoCache.Get(filePath); ok {
info = cachedInfo
}
}
if info == nil {
// 缓存未命中,调用 os.Stat
info, err = os.Stat(filePath)
if err != nil {
continue // 不存在,尝试下一个
}
if h.fileInfoCache != nil {
h.fileInfoCache.Set(filePath, info)
}
}
if info.IsDir() {
// 如果是目录,尝试查找索引文件
for _, idx := range h.index {
idxPath := filepath.Join(filePath, idx)
if idxInfo, err := os.Stat(idxPath); err == nil && !idxInfo.IsDir() {
var idxInfo os.FileInfo
if h.fileInfoCache != nil {
if cachedInfo, ok := h.fileInfoCache.Get(idxPath); ok {
idxInfo = cachedInfo
}
}
if idxInfo == nil {
idxInfo, err = os.Stat(idxPath)
if err != nil {
continue
}
if h.fileInfoCache != nil {
h.fileInfoCache.Set(idxPath, idxInfo)
}
}
if !idxInfo.IsDir() {
h.serveFile(ctx, idxPath, idxInfo, false)
return
}
@ -503,11 +534,28 @@ func (h *StaticHandler) handleInternalRedirect(ctx *fasthttp.RequestCtx, targetP
} else {
filePath = filepath.Join(h.root, targetPath)
}
info, err := os.Stat(filePath)
if err != nil {
utils.SendError(ctx, utils.ErrNotFound)
return
// 先查 FileInfo 缓存
var info os.FileInfo
var err error
if h.fileInfoCache != nil {
if cachedInfo, ok := h.fileInfoCache.Get(filePath); ok {
info = cachedInfo
}
}
if info == nil {
info, err = os.Stat(filePath)
if err != nil {
utils.SendError(ctx, utils.ErrNotFound)
return
}
if h.fileInfoCache != nil {
h.fileInfoCache.Set(filePath, info)
}
}
if info.IsDir() {
utils.SendError(ctx, utils.ErrForbidden)
return