mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
134 lines
3.4 KiB
Go
134 lines
3.4 KiB
Go
package middleware
|
||
|
||
import (
|
||
"net/http"
|
||
"strings"
|
||
"time"
|
||
|
||
"networkDev/utils/logger"
|
||
)
|
||
|
||
// LoggingMiddleware HTTP请求日志中间件
|
||
// 记录每个HTTP请求的详细信息,包括方法、路径、状态码和响应时间
|
||
type LoggingMiddleware struct {
|
||
logger *logger.Logger
|
||
}
|
||
|
||
// NewLoggingMiddleware 创建新的日志中间件实例
|
||
func NewLoggingMiddleware(logger *logger.Logger) *LoggingMiddleware {
|
||
return &LoggingMiddleware{
|
||
logger: logger,
|
||
}
|
||
}
|
||
|
||
// responseWriter 包装http.ResponseWriter以捕获状态码
|
||
type responseWriter struct {
|
||
http.ResponseWriter
|
||
statusCode int
|
||
written bool
|
||
}
|
||
|
||
// newResponseWriter 创建新的响应写入器包装器
|
||
func newResponseWriter(w http.ResponseWriter) *responseWriter {
|
||
return &responseWriter{
|
||
ResponseWriter: w,
|
||
statusCode: http.StatusOK, // 默认状态码
|
||
}
|
||
}
|
||
|
||
// WriteHeader 重写WriteHeader方法以捕获状态码
|
||
func (rw *responseWriter) WriteHeader(code int) {
|
||
if !rw.written {
|
||
rw.statusCode = code
|
||
rw.written = true
|
||
rw.ResponseWriter.WriteHeader(code)
|
||
}
|
||
}
|
||
|
||
// Write 重写Write方法以确保状态码被设置
|
||
func (rw *responseWriter) Write(b []byte) (int, error) {
|
||
if !rw.written {
|
||
rw.WriteHeader(http.StatusOK)
|
||
}
|
||
return rw.ResponseWriter.Write(b)
|
||
}
|
||
|
||
// Handler 中间件处理器函数
|
||
// 包装HTTP处理器以添加请求日志记录功能
|
||
func (lm *LoggingMiddleware) Handler(next http.Handler) http.Handler {
|
||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
start := time.Now()
|
||
|
||
// 包装响应写入器以捕获状态码
|
||
wrapped := newResponseWriter(w)
|
||
|
||
// 调用下一个处理器
|
||
next.ServeHTTP(wrapped, r)
|
||
|
||
// 计算响应时间
|
||
duration := time.Since(start)
|
||
|
||
// 记录请求日志
|
||
lm.logger.LogRequestWithHeaders(
|
||
r.Method,
|
||
r.URL.Path,
|
||
getClientIP(r),
|
||
wrapped.statusCode,
|
||
duration,
|
||
"-",
|
||
r.Header.Get("User-Agent"),
|
||
)
|
||
})
|
||
}
|
||
|
||
// getClientIP 获取客户端真实IP地址
|
||
// 优先从X-Forwarded-For、X-Real-IP等头部获取,最后使用RemoteAddr
|
||
func getClientIP(r *http.Request) string {
|
||
// 检查X-Forwarded-For头部
|
||
xForwardedFor := r.Header.Get("X-Forwarded-For")
|
||
if xForwardedFor != "" {
|
||
// X-Forwarded-For可能包含多个IP,取第一个
|
||
ips := strings.Split(xForwardedFor, ",")
|
||
if len(ips) > 0 {
|
||
return strings.TrimSpace(ips[0])
|
||
}
|
||
}
|
||
|
||
// 检查X-Real-IP头部
|
||
xRealIP := r.Header.Get("X-Real-IP")
|
||
if xRealIP != "" {
|
||
return xRealIP
|
||
}
|
||
|
||
// 检查X-Forwarded头部
|
||
xForwarded := r.Header.Get("X-Forwarded")
|
||
if xForwarded != "" {
|
||
return xForwarded
|
||
}
|
||
|
||
// 使用RemoteAddr
|
||
remoteAddr := r.RemoteAddr
|
||
if strings.Contains(remoteAddr, ":") {
|
||
// 移除端口号
|
||
if idx := strings.LastIndex(remoteAddr, ":"); idx != -1 {
|
||
return remoteAddr[:idx]
|
||
}
|
||
}
|
||
|
||
return remoteAddr
|
||
}
|
||
|
||
// WrapHandler 包装HTTP处理器以添加日志记录功能
|
||
// 使用全局日志记录器创建日志中间件
|
||
func WrapHandler(handler http.Handler) http.Handler {
|
||
logger := logger.GetLogger()
|
||
middleware := NewLoggingMiddleware(logger)
|
||
return middleware.Handler(handler)
|
||
}
|
||
|
||
// WrapHandlerFunc 包装HTTP处理器函数以添加日志记录功能
|
||
// 将HandlerFunc转换为Handler并添加日志中间件
|
||
func WrapHandlerFunc(handlerFunc http.HandlerFunc) http.Handler {
|
||
return WrapHandler(handlerFunc)
|
||
}
|