lolly/internal/handler/static.go
xfy b445bca96a feat(server): 实现基础 HTTP 服务器核心功能
使用 fasthttp 替代 net/http,实现 Phase 2 核心模块:
- HTTP 服务器:fasthttp.Server 配置超时和连接限制
- 路由系统:fasthttp/router 基于 radix tree 匹配
- 静态文件服务:安全检查、索引文件支持
- 日志系统:zerolog 结构化日志
- 中间件框架:链式组合接口
- 虚拟主机管理:按 Host 头选择处理器

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-02 15:23:54 +08:00

57 lines
1.2 KiB
Go

package handler
import (
"os"
"path/filepath"
"strings"
"github.com/valyala/fasthttp"
)
// StaticHandler 静态文件处理器
type StaticHandler struct {
root string
index []string
}
// NewStaticHandler 创建静态文件处理器
func NewStaticHandler(root string, index []string) *StaticHandler {
return &StaticHandler{root: root, index: index}
}
// Handle 处理静态文件请求
func (h *StaticHandler) Handle(ctx *fasthttp.RequestCtx) {
path := string(ctx.Path())
// 安全检查:防止目录遍历
if strings.Contains(path, "..") {
ctx.Error("Forbidden", fasthttp.StatusForbidden)
return
}
// 拼接文件路径
filePath := filepath.Join(h.root, path)
// 检查文件/目录是否存在
info, err := os.Stat(filePath)
if err != nil {
ctx.Error("Not Found", fasthttp.StatusNotFound)
return
}
// 如果是目录,尝试索引文件
if info.IsDir() {
for _, idx := range h.index {
idxPath := filepath.Join(filePath, idx)
if _, err := os.Stat(idxPath); err == nil {
fasthttp.ServeFile(ctx, idxPath)
return
}
}
ctx.Error("Forbidden", fasthttp.StatusForbidden)
return
}
// 直接返回文件
fasthttp.ServeFile(ctx, filePath)
}