代码推送
This commit is contained in:
78
internal/middleware/access_log.go
Normal file
78
internal/middleware/access_log.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gotest/internal/geoip"
|
||||
"gotest/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// responseWriter 包装 gin.ResponseWriter 以捕获状态码
|
||||
type responseWriter struct {
|
||||
gin.ResponseWriter
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (w *responseWriter) WriteHeader(code int) {
|
||||
w.statusCode = code
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
// AccessLog 访问日志中间件,记录每次 HTTP 请求到数据库
|
||||
func AccessLog(db *gorm.DB, ipService *geoip.Service) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 跳过健康检查和静态资源
|
||||
path := c.Request.URL.Path
|
||||
if path == "/api/health" || strings.HasPrefix(path, "/shared/") || strings.HasPrefix(path, "/assets/") {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
clientIP := c.ClientIP()
|
||||
|
||||
// 包装响应写入器以捕获状态码
|
||||
rw := &responseWriter{ResponseWriter: c.Writer, statusCode: http.StatusOK}
|
||||
c.Writer = rw
|
||||
|
||||
c.Next()
|
||||
|
||||
// 异步写入日志(不阻塞请求响应)
|
||||
go func() {
|
||||
cost := int(time.Since(start).Milliseconds())
|
||||
ua := c.Request.UserAgent()
|
||||
if len(ua) > 500 {
|
||||
ua = ua[:500]
|
||||
}
|
||||
referer := c.Request.Referer()
|
||||
if len(referer) > 500 {
|
||||
referer = referer[:500]
|
||||
}
|
||||
p := c.Request.URL.Path
|
||||
if len(p) > 500 {
|
||||
p = p[:500]
|
||||
}
|
||||
|
||||
// 查询 IP 归属地
|
||||
location := ipService.Lookup(clientIP)
|
||||
|
||||
log := model.AccessLog{
|
||||
IP: clientIP,
|
||||
Path: p,
|
||||
Method: c.Request.Method,
|
||||
UserAgent: ua,
|
||||
Referer: referer,
|
||||
Location: location,
|
||||
Status: rw.statusCode,
|
||||
Cost: cost,
|
||||
}
|
||||
|
||||
db.Create(&log)
|
||||
}()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user