go-first/internal/middleware/middleware.go
2026-10-07 15:21:47 +02:00

100 lines
2.5 KiB
Go

package middleware
import (
"time"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
)
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
c.Next()
latency := time.Since(start)
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
bodySize := c.Writer.Size()
if raw != "" {
path = path + "?" + raw
}
log.Info().
Str("method", method).
Str("path", path).
Int("status", statusCode).
Dur("latency", latency).
Str("client_ip", clientIP).
Int("body_size", bodySize).
Msg("HTTP request")
}
}
func Recovery() gin.HandlerFunc {
return gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
log.Error().
Interface("error", recovered).
Str("path", c.Request.URL.Path).
Msg("Panic recovered")
c.JSON(500, gin.H{
"success": false,
"error": gin.H{
"code": "INTERNAL_ERROR",
"message": "Internal server error",
},
})
c.Abort()
})
}
func CORS(allowedOrigins []string) gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
allowed := false
for _, o := range allowedOrigins {
if o == "*" || o == origin {
allowed = true
break
}
}
if allowed {
c.Writer.Header().Set("Access-Control-Allow-Origin", origin)
}
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
func SecurityHeaders() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("X-Content-Type-Options", "nosniff")
c.Writer.Header().Set("X-Frame-Options", "DENY")
c.Writer.Header().Set("X-XSS-Protection", "1; mode=block")
c.Writer.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
c.Writer.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'")
c.Next()
}
}
func RateLimiter(requests int, window time.Duration) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
}
}