65 Commits

Author SHA1 Message Date
xfy
26d62c9fcd refactor(handler): improve autoindex code quality
Use fmt.Fprintf directly on buffer instead of buf.WriteString(fmt.Sprintf(...)),
handle dir.Close error in defer, use blank identifier for unused parameter,
use range-over-int, and remove trailing blank line.

💘 Generated with Crush

Assisted-by: GLM 5.1 via Crush <crush@charm.land>
2026-04-30 16:23:34 +08:00
xfy
5f470993ff perf(handler): use RWMutex for FileInfoCache
- Change FileInfoCache.mu from sync.Mutex to sync.RWMutex
- Get method uses RLock for concurrent read access
- Stats method uses RLock for read-only operation
- Double-check pattern for lock upgrades (TTL expiry, LRU move)

This improves concurrent read performance for the FileInfo cache,
which is read-heavy in static file serving scenarios.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 16:15:39 +08:00
xfy
3c96f12f74 feat(cache): store ContentType in FileEntry for cache hits
- Add ContentType field to FileEntry struct
- Update Set method signature to accept contentType parameter
- Use cached ContentType in static.go cache hit branches
- Update all test files to use new Set signature

This avoids redundant MIME type detection on cache hits,
reducing lock contention in mimeutil.DetectContentType.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 16:13:42 +08:00
xfy
23fdcf89ae perf(handler): use cached ETag to avoid regeneration on cache hits
- Use entry.ETag instead of generateETag() in cache hit branches
- Add 304 response check before returning cached data
- Reduces ETag computation overhead for cached files

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 16:03:59 +08:00
xfy
73ef3a938b 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>
2026-04-30 15:56:42 +08:00
xfy
3b608be0de refactor(handler): improve autoindex code quality
- Replace custom escape functions with stdlib html.EscapeString and url.PathEscape
- Fix benchmark test file naming using fmt.Sprintf
- Add CSP security header for HTML output
- Add empty directory test case
- Remove obsolete escape function tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 15:21:10 +08:00
xfy
b62a3f12da feat(handler): add autoindex module for directory listing
Add nginx-like autoindex functionality with three output formats:
- HTML: styled directory listing with sortable columns
- JSON: structured API-friendly output
- XML: machine-readable format

Configuration options:
- auto_index: enable/disable directory listing
- auto_index_format: output format (html/json/xml)
- auto_index_localtime: use local time instead of GMT
- auto_index_exact_size: show exact bytes vs human-readable

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 15:11:34 +08:00
xfy
8cc3fdef6f perf(handler): optimize static file serving performance
- Add pathPrefixLen for zero-allocation path stripping
- Precompute ETag in FileCache.Set, reuse on cache hits
- Add MIME LRU cache with O(1) operations using container/list
- Remove sharded cache (eager LRU was slower than single-lock)
- Add FileInfo cache to reduce os.Stat calls (TTL-only strategy)
- Adjust test expectations for normalized root path format

Benchmark results: Lookup 12.7µs → 10.6µs (16% improvement)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 14:17:56 +08:00
xfy
d269940d8b style: fix formatting issues
- Add missing newlines at end of files
- Fix indentation in ssl.go
- Remove extra blank lines

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 13:42:53 +08:00
xfy
b1e1547e36 fix(lint): resolve errcheck and goconst issues
- Add nolint comments for sync.Pool.Get() type assertions (pool always returns valid pointers)
- Extract TLS version strings to constants in sslutil/tlsconfig.go
- Extract expires directive strings to constants in handler/static.go

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 13:41:15 +08:00
xfy
fc586d4ace fix(handler): normalize root path to fix relative path performance
When root is configured as a relative path (e.g., "./lib/site/"),
filepath.Join normalizes it to "lib/site/" but the original value
was stored in h.root. This caused strings.TrimPrefix in serveFile
to fail, resulting in incorrect path calculations for GzipStatic.

The bug caused every request to attempt opening a non-existent
precompressed file path like "lib/site/lib/site/index.html.gz",
adding an extra failed os.Stat call per request and reducing
performance by ~50%.

Fix by normalizing root with filepath.Clean in NewStaticHandler
and SetRoot to ensure TrimPrefix works correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 13:29:26 +08:00
xfy
f145a8770e refactor: modernize code with Go 1.22+ features
Apply modern Go patterns across the codebase:
- Replace `interface{}` with `any` (Go 1.18+)
- Use `for range n` instead of `for i := 0; i < n; i++` (Go 1.22+)
- Replace `sort.Slice` with `slices.Sort` from slices package
- Simplify sync.WaitGroup patterns with errgroup where appropriate
- Add Makefile targets for modernize analyzer

Total: 84 files updated, net reduction of 79 lines

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 10:37:45 +08:00
xfy
4dfd6df38b style(handler): add missing newline at EOF
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 18:30:14 +08:00
xfy
a365cd2033 refactor(handler): separate sendfile common code
Create sendfile_common.go for shared constants and functions:
- MinSendfileSize constant
- getNetConn helper
- copyFile fallback function

Platform-specific files now only contain platform implementations.
Eliminates ~50 lines of duplicate code between Linux and non-Linux.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 18:24:15 +08:00
xfy
11e22c80b8 perf: 零分配优化与 Dial timeout 支持
- 添加 b2s/s2b 零分配字节-字符串转换工具函数
- WebSocket 数据转发使用 sync.Pool 复用 32KB buffer
- 条件化 Debug 日志避免非 Debug 级别的字符串分配
- 缓存键哈希计算直接写入 []byte 避免 string 转换
- 使用 bytes.EqualFold 替代 strings.ToLower 进行大小写不敏感比较
- generateETag 使用 strconv.AppendInt 避免 fmt.Sprintf
- 支持 Dial timeout 配置,区分 TCP 连接建立和总连接超时
- MaxConnsPerHost 默认值改为 512(fasthttp 推荐)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 20:11:20 +08:00
xfy
cf2fcca7e8 refactor: 提取公共逻辑、消除重复代码、加强错误处理
- 提取 App 公共逻辑到 app_common.go,消除 app.go/app_windows.go 重复定义
- 提取 Server 生命周期/中间件/路由逻辑到独立文件(lifecycle.go/middleware_builder.go/router.go)
- 提取 Proxy 缓存处理/头部修改/目标选择到独立模块
- 提取 CheckIPAccess/CheckTokenAuth 到 utils/httperror.go,消除 status/purge 重复实现
- 修复 stream 双向转发:任一方向完成立即关闭双端,避免连接泄漏
- 修复 SSL/TLS 中静默忽略错误的问题,添加日志记录
- 统一日志消息为英文

💘 Generated with Crush

Assisted-by: GLM 5.1 via Crush <crush@charm.land>
2026-04-28 18:00:48 +08:00
xfy
5574339d28 test: 完善测试覆盖率和 E2E 测试场景
Phase 1: 单元测试补充
- 新增 config/loader_test.go,覆盖配置加载、include 合并、循环检测
- 补充 cache/cache_test.go,测试 RefreshCachedAt、DeleteByPatternWithMethod
- 补充 handler/static_test.go,测试 SetExpires、setCacheHeaders、parseExpires

Phase 2: E2E 测试扩展
- 新增 ratelimit_e2e_test.go,测试请求限流功能
- 新增 compression_e2e_test.go,测试 Gzip 压缩功能
- 新增 access_e2e_test.go,测试 IP 访问控制
- 新增 rewrite_e2e_test.go,测试 URL 重写和重定向

覆盖率提升: 82.3% -> 83.1%
E2E 测试用例: ~84 -> ~104 (+20)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-27 17:06:55 +08:00
xfy
d191e1865d feat(static): 添加 expires 缓存控制支持
- StaticConfig 添加 Expires 字段,支持 nginx 兼容格式(30d, 1h, max, epoch)
- StaticHandler 添加 SetExpires 方法和缓存响应头设置
- serveFile 自动设置 Cache-Control 和 Expires 响应头
- nginx 转换器正确转换 expires 指令
- --generate-config 输出包含 expires 文档和示例

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-27 14:05:25 +08:00
xfy
65cdab60f9 feat(handler): 静态文件支持 ETag 和 304 Not Modified
添加 generateETag 和 isNotModified 函数,在所有响应路径设置
ETag/Last-Modified 头,支持 If-None-Match 和 If-Modified-Since
条件请求返回 304,减少不必要的文件传输。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 13:13:31 +08:00
xfy
8f79fb6797 test(config,handler,loadbalance,proxy): 扩展单元测试覆盖率
添加以下测试:
- validate_test.go: Rewrite、NextUpstream、DefaultServer、Mode、
  ListenConflicts、HTTP2、RedirectRewrite 验证测试
- sendfile_test.go: 无效文件描述符、零长度传输、部分传输、
  带偏移量传输测试
- balancer_test.go: ConsistentHash Select/SelectExcluding、
  RandomBalancer 边界条件和 Power of Two Choices 测试
- health_test.go: MarkHealthy/MarkUnhealthy 与 SlowStartManager
  集成测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 18:28:28 +08:00
xfy
2bdc8f3b3b refactor(handler,middleware,server): 增强预压缩配置灵活性
- NewGzipStatic 增加 precompressedExtensions 参数,支持自定义预压缩扩展名
- SetGzipStatic 分离源文件扩展名和预压缩扩展名参数
- 更新相关测试用例

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:35:03 +08:00
xfy
9f7090df67 test(handler,middleware,server,ssl,proxy): 扩展测试覆盖率
- handler: 添加 sendfile 和 static 处理器测试
- middleware/security: 添加访问控制、认证、请求头、限流测试
- server: 添加池、pprof、清理、状态、升级、vhost 测试
- ssl: 添加客户端验证、OCSP、SSL 测试
- proxy: 添加代理覆盖率补充测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 10:42:05 +08:00
xfy
ae0bec6c3b feat(internal): 实现 internal 指令
- 新增 IsInternalRedirect 检测内部重定向请求
- static handler 支持 internal 访问限制
- proxy handler 支持 internal 访问限制
- 支持 X-Accel-Redirect 内部重定向

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 18:09:06 +08:00
xfy
2458ac1ed1 docs: 为其余模块添加标准化 godoc 注释
为剩余模块添加完整文档注释:
- app: 应用生命周期管理
- cache: 文件缓存
- config: 配置加载器
- handler: 静态文件处理和错误页面
- http2/http3: HTTP/2 和 HTTP/3 适配器
- loadbalance: 负载均衡算法和均衡器
- middleware: bodylimit、compression、rewrite、security
- mimeutil: MIME 类型检测
- netutil: URL 处理工具
- resolver: DNS 解析器
- server: 服务器升级处理
- ssl: SSL/TLS 和 OCSP
- stream: 流处理
- testutil: 测试工具
- variable: 变量池和 SSL 变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-20 10:59:53 +08:00
xfy
04f6caa40d test(handler): 添加静态文件发送处理测试
- 测试 SendFile 基本功能和错误处理
- 测试 Range 请求支持
- 测试不同文件类型和 MIME 类型

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 18:12:28 +08:00
xfy
8ed800271d test: 迁移基准测试循环到 Go 1.24 b.Loop() API
- 所有 *_bench_test.go 文件从 for i := 0; i < b.N; i++ 改为 for b.Loop()
- 部分测试文件从 for i := 0; i < N; ... 改为 for range N 或 for i := range N
- 涵盖模块: cache, handler, http2, http3, loadbalance, logging, lua,
  middleware/accesslog, middleware/bodylimit, middleware/rewrite,
  middleware/security, netutil, resolver, server, ssl, stream

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 13:50:15 +08:00
xfy
d874f97765 fix(handler): 修复 sendfile 高并发下的连接断开处理
- EPIPE/ECONNRESET 不再 fallback,直接返回错误避免响应混乱
- 正确处理 EAGAIN/EWOULDBLOCK socket 缓冲区满,等待重试
- EINTR 信号中断正确重试
- 改用 SetBodyStream 确保 HTTP 头先发送再 sendfile
- 添加重试限制(100次)防止无限循环

测试结果:0 错误/100000 并发请求

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 09:54:08 +08:00
xfy
fa55bfd497 feat(cache): 添加缓存 TTL 新鲜度验证优化
在 FileEntry 中新增 CachedAt 字段记录缓存时间,实现 TTL 窗口内的缓存新鲜度验证:
- TTL 内跳过 ModTime 验证,减少 os.Stat 调用
- TTL 过期后验证 ModTime,文件未修改时刷新 CachedAt
- 默认 TTL 设置为 5 秒

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 17:53:51 +08:00
xfy
73ef7f4916 fix(lint): 修复剩余 lint 错误
- 统一八进制权限格式为 Go 1.13+ 风格 (0o644/0o755)
- 调整 Target 结构体字段顺序优化内存对齐
- 合并相邻的全局变量声明
- 删除多余空行
- 更新 Makefile 使用 gofumpt 替代 goimports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 16:50:14 +08:00
xfy
b722cbf884 style: 统一八进制权限格式和代码格式 2026-04-13 16:40:50 +08:00
xfy
ef652cdab1 feat(static): 添加符号链接安全检查功能 2026-04-13 16:40:50 +08:00
xfy
d21e27fbac fix(lint): 修复 golangci-lint 错误 (119 -> 0 issues)
主要修复:
- errcheck: defer Close 使用 //nolint:errcheck,类型断言改为 ok 检查
- govet fieldalignment: 调整结构体字段顺序优化内存布局
- revive unused-parameter: 将未使用参数改为 _
- exhaustive: 添加缺失的 switch case 或 default
- goconst: 提取重复字符串为常量 (accessAllow, accessDeny 等)
- staticcheck SA9003: 修复空分支逻辑
- gofmt: 运行 gofmt -w 格式化
- nolintlint: 修复 nolint 注释格式

其他改进:
- 更新 .golangci.yml 配置,启用更严格的检查
- 移除未使用的代码和导入
- 简化测试辅助函数调用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 16:15:31 +08:00
xfy
e646cc5d05 refactor(test): 提取 testutil 包统一测试辅助函数
- 新增 NewRequestCtx 和 NewRequestCtxWithHeader 辅助函数
- 简化各测试文件中 RequestCtx 创建代码
- 减少测试代码重复,提高可维护性

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 13:15:20 +08:00
xfy
e1df0ec205 refactor(utils): 提取 HTTP 错误响应辅助函数
新增 SendError 和 SendErrorWithDetail 函数,统一处理 HTTP 错误响应,减少重复代码。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:12:49 +08:00
xfy
bb77fa6a98 fix(lint): 修复 handler 和 http2 模块 lint 错误
- 添加 nolint:errcheck 注释到 defer Close 调用
- 修复 websocket.go 中重复的 nolint 注释格式
- 添加 staticcheck SA1019 nolint 注释到 deprecated WriteScheduler
- 移除 sendfile_linux.go 中未使用的 platformLinux 常量
- 添加文件末尾换行符

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:51:30 +08:00
xfy
8b382606df Merge branch 'lint-fix' - resolve sendfile.go conflict
Conflict: sendfile.go (!linux build tag) was incorrectly modified to
include linuxSendfile and getSocketFd functions which already exist
in sendfile_linux.go.

Resolution: Keep HEAD version (simple fallback returning ENOTSUP) as
Linux implementation is properly separated in sendfile_linux.go.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:26:48 +08:00
xfy
92ef122226 refactor(handler): 拆分 sendfile 实现为平台特定文件
- Linux 平台保留 sendfile 系统调用的零拷贝实现
- 非 Linux 平台使用普通 IO fallback
- 分离平台特定测试到独立文件

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 11:45:46 +08:00
xfy
76c2a6028c feat(handler,config): 支持 try_files 动态后缀 ($uri.<ext>)
- 实现 $uri.<ext> 模式解析(如 $uri.html, $uri.json)
- 添加扩展名安全验证:白名单字符、危险后缀黑名单
- 根路径边界处理:避免生成 "/.html" 隐藏文件名
- 增强配置文档注释,说明 nginx 兼容性和安全限制
- 完整单元测试覆盖

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 18:30:28 +08:00
xfy
93e3ee0b14 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>
2026-04-10 16:55:37 +08:00
xfy
a965040eff refactor(handler): 提取平台字符串为常量
- 使用 platformLinux 常量替代硬编码字符串 "linux"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 11:20:35 +08:00
xfy
4e826925ac refactor: 适配核心模块类型重命名
适配 variable.NewContext/ReleaseContext
适配 resolver.DNSCacheEntry
适配 logging/formatJSON 常量

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 09:41:07 +08:00
xfy
84c26c61ca style(benchmark): 修复代码格式和忽略无用错误返回值 2026-04-09 12:19:08 +08:00
xfy
25bdba4e01 test(benchmark): 新增组件级基准测试套件
- 新增 benchmark_context.go 标准化测试上下文构造器
- 新增静态文件处理器基准测试(缓存命中/未命中、try_files)
- 新增访问日志中间件基准测试
- 新增压缩中间件基准测试(gzip/brotli、Pool 复用)
- 新增限流器基准测试(令牌桶、滑动窗口、多客户端并发)
- 新增变量展开基准测试(模板展开、Pool 操作)
2026-04-08 18:25:38 +08:00
xfy
84d67c8570 feat(handler/static): 新增 alias 指令支持路径别名
- NewStaticHandlerWithAlias 创建带 alias 的静态文件处理器
- alias 与 root 互斥,支持路径替换而非附加
- 新增测试覆盖 alias 路径映射逻辑

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-08 14:37:20 +08:00
xfy
b72394eb3b style(handler,server): 格式化测试代码结构体字段对齐
- 对齐 errorpage_test.go、static_test.go、pprof_test.go 中的结构体字段
- 纯代码格式化,无逻辑变更

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-08 13:30:00 +08:00
xfy
b6f8894d78 test(handler,middleware,server): 新增 try_files、错误页面、pprof 单元测试
- static_test.go: 新增 try_files 配置解析、占位符解析、SPA 场景测试
- errorpage_test.go: 新增错误页面管理器完整测试覆盖
- errorintercept_test.go: 新增错误拦截中间件功能测试
- pprof_test.go: 新增 pprof 性能分析端点测试

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-08 11:15:39 +08:00
xfy
23f5c08614 feat(handler,server): 静态文件新增 try_files 配置,集成新增中间件
- StaticHandler 支持 try_files 配置,用于 SPA 部署回退
- 支持 $uri 和 $uri/ 占位符解析
- Server 集成 bodylimit 中间件(全局和路径级别配置)
- Server 集成 errorintercept 中间件(错误页面拦截)
- Server 预加载错误页面到内存

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 17:50:38 +08:00
xfy
827d26c2b5 feat(handler,middleware,errorintercept): 新增自定义错误页面支持
- ErrorPageManager 预加载错误页面到内存,运行时无文件 I/O
- ErrorIntercept 中间件拦截 4xx/5xx 响应并应用自定义页面
- 支持特定状态码页面和默认页面配置
- 支持可选的响应状态码覆盖(如返回 200 OK)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 17:49:59 +08:00
xfy
83e1fe38ba feat(config,handler,server): 支持多静态目录配置,新增路径前缀匹配
- Static 配置从单对象改为数组,支持多个静态目录
- StaticConfig 新增 Path 字段用于路径前缀匹配
- 添加 validateStatics 和 validatePathConflicts 验证函数
- 删除 config.example.yaml 示例文件(配置可通过 --generate 生成)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-07 16:26:55 +08:00
xfy
f2352ab9cc docs(config,stream,logging,handler,proxy,cache,server,ssl,middleware): 为核心模块添加详细 GoDoc 文档注释
- config: 为 Config 和所有子配置结构添加完整文档,包含使用示例和注意事项
- stream: 为负载均衡器和服务器添加详细的参数、返回值和功能说明
- logging: 为日志格式化和输出函数添加文档,说明支持的变量替换
- handler: 为路由器、静态文件和 sendfile 处理器添加文档
- proxy: 为健康检查器和代理功能添加完整文档
- cache/server/ssl/middleware: 补充相关模块的文档注释
- config.example.yaml: 添加可信代理配置、加密套件示例,更新压缩级别说明

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-07 15:36:09 +08:00