80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"github.com/gin-gonic/gin"
|
||
"os"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
var (
|
||
ipLogFilePath string
|
||
ipLogMu sync.Mutex
|
||
)
|
||
|
||
// EnsureIPLogPathInitialized 初始化IP日志文件路径。
|
||
// 作用:根据运行系统设置默认存储位置,并确保目录存在,避免写入失败。
|
||
// 优先读取环境变量 IP_LOG_FILE(例如:/www/wwwroot/centerBook/ip.txt)。
|
||
// Windows 默认:C:\Users\www\centerBook\ip.txt;Linux 默认:/www/wwwroot/centerBook/ip.txt。
|
||
func EnsureIPLogPathInitialized() {
|
||
if ipLogFilePath != "" {
|
||
return
|
||
}
|
||
if env := os.Getenv("IP_LOG_FILE"); env != "" {
|
||
ipLogFilePath = env
|
||
} else {
|
||
if runtime.GOOS == "windows" {
|
||
ipLogFilePath = `C:\Users\www\centerBook\ip.txt`
|
||
} else {
|
||
ipLogFilePath = "/www/wwwroot/centerBook/ip.txt"
|
||
}
|
||
}
|
||
dir := filepath.Dir(ipLogFilePath)
|
||
_ = os.MkdirAll(dir, 0755)
|
||
}
|
||
|
||
// LogLargePerPage 记录超大 per_page 请求的IP信息到文本文件。
|
||
// 触发条件:当 per_page 被裁剪(原始值大于上限)时调用。
|
||
// 记录内容:时间、IP、方法、原始per_page、裁剪后per_page、路径、UA。
|
||
func LogLargePerPage(c *gin.Context, originalPerPage, sanitizedPerPage int) {
|
||
EnsureIPLogPathInitialized()
|
||
line := fmt.Sprintf(
|
||
"%s | ip=%s | method=%s | per_page=%d->%d | path=%s | ua=%s\n",
|
||
time.Now().Format("2006-01-02 15:04:05"),
|
||
c.ClientIP(),
|
||
c.Request.Method,
|
||
originalPerPage,
|
||
sanitizedPerPage,
|
||
c.Request.RequestURI,
|
||
strings.ReplaceAll(c.GetHeader("User-Agent"), "\n", " "),
|
||
)
|
||
ipLogMu.Lock()
|
||
defer ipLogMu.Unlock()
|
||
f, err := os.OpenFile(ipLogFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||
if err != nil {
|
||
// 静默失败,避免影响主流程
|
||
return
|
||
}
|
||
defer f.Close()
|
||
_, _ = f.WriteString(line)
|
||
}
|
||
|
||
// IPLogHandler 返回 ip.txt 的内容(text/plain)。
|
||
// 用途:通过路由暴露 ip.txt,便于反向代理将 https://book.center.buzhiyushu.cn/ip.txt 映射到此接口。
|
||
func IPLogHandler() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
EnsureIPLogPathInitialized()
|
||
data, err := os.ReadFile(ipLogFilePath)
|
||
if err != nil {
|
||
c.String(200, "")
|
||
return
|
||
}
|
||
c.Header("Content-Type", "text/plain; charset=utf-8")
|
||
c.String(200, string(data))
|
||
}
|
||
}
|