This commit is contained in:
2026-05-12 01:13:01 +02:00
commit bf304e17c9
46 changed files with 4358 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
package middleware
import (
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"log/slog"
"net"
"net/http"
"runtime/debug"
"time"
"github.com/labstack/echo/v4"
)
func RequestID() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
id := c.Request().Header.Get(echo.HeaderXRequestID)
if id == "" {
id = newRequestID()
}
c.Response().Header().Set(echo.HeaderXRequestID, id)
c.Set(echo.HeaderXRequestID, id)
return next(c)
}
}
}
func newRequestID() string {
var buf [16]byte
if _, err := rand.Read(buf[:]); err != nil {
return fmt.Sprintf("req-%d", time.Now().UnixNano())
}
return hex.EncodeToString(buf[:])
}
func RealIP() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if forwarded := c.Request().Header.Get("X-Forwarded-For"); forwarded != "" {
c.Set("real_ip", forwarded)
} else if host, _, err := net.SplitHostPort(c.Request().RemoteAddr); err == nil {
c.Set("real_ip", host)
}
return next(c)
}
}
}
func AccessLog(logger *slog.Logger) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
start := time.Now()
err := next(c)
session := GetSession(c)
customerID := int64Value(session.CustomerID)
cartID := int64Value(session.CartID)
logger.Info("request complete",
"method", c.Request().Method,
"path", c.Request().URL.Path,
"status", c.Response().Status,
"latency_ms", time.Since(start).Milliseconds(),
"request_id", c.Response().Header().Get(echo.HeaderXRequestID),
"parse_status", session.ParseStatus,
"customer_id", customerID,
"cart_id", cartID,
)
return err
}
}
}
func Recover(logger *slog.Logger) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
defer func() {
if recovered := recover(); recovered != nil {
logger.Error("panic recovered", "error", recovered, "stack", string(debug.Stack()))
_ = c.JSON(http.StatusInternalServerError, map[string]string{"error": "internal server error"})
}
}()
return next(c)
}
}
}
func HTTPErrorHandler(logger *slog.Logger) echo.HTTPErrorHandler {
return func(err error, c echo.Context) {
if c.Response().Committed {
return
}
var httpErr *echo.HTTPError
code := http.StatusInternalServerError
message := map[string]string{"error": "internal server error"}
if errors.As(err, &httpErr) {
code = httpErr.Code
if msg, ok := httpErr.Message.(string); ok {
message = map[string]string{"error": msg}
}
}
logger.Error("request failed", "status", code, "error", err)
_ = c.JSON(code, message)
}
}
func int64Value(value *int64) any {
if value == nil {
return nil
}
return *value
}