- 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>
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
//go:build !linux
|
||
|
||
// Package handler 提供 HTTP 请求处理器,包括路由、静态文件服务和零拷贝传输。
|
||
//
|
||
// 该文件包含非 Linux 平台的 sendfile 实现(使用 fallback 方式)。
|
||
//
|
||
// 作者:xfy
|
||
package handler
|
||
|
||
import (
|
||
"os"
|
||
"syscall"
|
||
|
||
"github.com/valyala/fasthttp"
|
||
)
|
||
|
||
// SendFile 零拷贝文件传输。
|
||
//
|
||
// 大文件使用系统调用直接从文件传输到 socket,避免用户空间拷贝,
|
||
// 从而减少 CPU 和内存开销,提升传输性能。
|
||
//
|
||
// 参数:
|
||
// - ctx: fasthttp 请求上下文,用于获取底层连接
|
||
// - file: 要传输的文件对象
|
||
// - offset: 文件起始偏移量(字节)
|
||
// - length: 传输长度(字节),-1 表示传输到文件末尾
|
||
//
|
||
// 返回值:
|
||
// - error: 传输过程中的错误
|
||
//
|
||
// 注意事项:
|
||
// - 小于 8KB 的文件使用普通 io.Copy
|
||
// - 非 Linux 平台(macOS、Windows)使用 fallback 方式
|
||
//
|
||
// 使用示例:
|
||
//
|
||
// file, _ := os.Open("large_file.bin")
|
||
// defer file.Close()
|
||
// info, _ := file.Stat()
|
||
// err := SendFile(ctx, file, 0, info.Size())
|
||
func SendFile(ctx *fasthttp.RequestCtx, file *os.File, offset, length int64) error {
|
||
// 小文件使用普通 io.Copy
|
||
if length < MinSendfileSize {
|
||
return copyFile(ctx, file, offset, length)
|
||
}
|
||
|
||
// 尝试获取 socket 文件描述符
|
||
conn := getNetConn(ctx)
|
||
if conn == nil {
|
||
return copyFile(ctx, file, offset, length)
|
||
}
|
||
|
||
// 非 Linux 平台使用 fallback
|
||
err := platformSendfile(conn, file, offset, length)
|
||
if err != nil {
|
||
// sendfile 失败,fallback 到 io.Copy
|
||
return copyFile(ctx, file, offset, length)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// platformSendfile 非 Linux 平台的 sendfile 实现。
|
||
//
|
||
// macOS 和 Windows 不支持 sendfile 系统调用,返回 ENOTSUP 触发 fallback。
|
||
//
|
||
// 参数:
|
||
// - conn: 目标网络连接
|
||
// - file: 源文件对象
|
||
// - offset: 文件起始偏移量
|
||
// - length: 传输长度
|
||
//
|
||
// 返回值:
|
||
// - error: 始终返回 ENOTSUP,表示不支持
|
||
func platformSendfile(conn any, file *os.File, offset, length int64) error {
|
||
// macOS sendfile 签名复杂,简化使用 fallback
|
||
// Windows TransmitFile 需要特殊 API
|
||
return syscall.ENOTSUP
|
||
}
|