AndreyIgorevich d9ffefd5f6 Add project
2025-07-10 01:10:47 +07:00

76 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package middleware
import (
"context"
"log/slog"
"net"
"net/http"
"strings"
"yobbly-gateway-go/internal/logger"
)
type contextKey string
const realIPContextKey contextKey = "realIP"
// RealIPMiddleware извлекает реальный IP-адрес клиента из заголовков и устанавливает его в контекст запроса.
func RealIPMiddleware(next http.Handler) http.Handler {
op := "middleware.RealIPMiddleware"
log := logger.NewLoggerWithOp(op)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
realIP := r.Header.Get("X-Real-IP")
if realIP == "" {
forwardedFor := r.Header.Get("X-Forwarded-For")
if forwardedFor != "" {
parts := strings.Split(forwardedFor, ",")
realIP = strings.TrimSpace(parts[0])
}
}
if realIP != "" {
_, port, err := net.SplitHostPort(r.RemoteAddr)
if err == nil {
r.RemoteAddr = net.JoinHostPort(realIP, port)
} else {
r.RemoteAddr = realIP
}
ctx := context.WithValue(r.Context(), realIPContextKey, realIP)
r = r.WithContext(ctx)
log.Debug("real IP extracted", slog.String("ip", realIP))
}
next.ServeHTTP(w, r)
})
}
// GetRealIP извлекает реальный IP из контекста запроса.
func GetRealIP(r *http.Request) string {
if ip, ok := r.Context().Value(realIPContextKey).(string); ok {
return ip
}
return r.RemoteAddr
}
// RemoveTrailingSlashMiddleware перенаправляет запросы с завершающим слэшем (если это не просто '/')
// на тот же путь без завершающего слэша.
func RemoveTrailingSlashMiddleware(next http.Handler) http.Handler {
op := "middleware.RemoveTrailingSlashMiddleware"
log := logger.NewLoggerWithOp(op)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
if urlPath != "" && urlPath != "/" && strings.HasSuffix(urlPath, "/") {
newPath := strings.TrimSuffix(urlPath, "/")
newURL := *r.URL
newURL.Path = newPath
log.Debug("redirecting trailing slash", slog.String("old_path", urlPath), slog.String("new_path", newPath))
http.Redirect(w, r, newURL.String(), http.StatusMovedPermanently)
return
}
next.ServeHTTP(w, r)
})
}