Files
galaxy-game/backend/internal/server/clientip/clientip.go
T
2026-05-06 10:14:55 +03:00

42 lines
1.4 KiB
Go

// Package clientip exposes the helper that resolves the originating client
// IP for an inbound HTTP request. Backend trusts the value because the
// network segment between gateway and backend is the trust boundary
// (`ARCHITECTURE.md` §15-16): gateway is responsible for sanitising and
// populating `X-Forwarded-For` before the request reaches backend.
//
// Both the public-auth handler chain (handlers_auth_helpers.go) and the
// user-surface geo-counter middleware reuse the same extraction so the two
// surfaces never disagree about the IP they record.
package clientip
import (
"net"
"strings"
"github.com/gin-gonic/gin"
)
// ExtractSourceIP returns the originating client IP for the request behind
// c. The leftmost entry of `X-Forwarded-For` is preferred; when the header
// is absent or empty, the connection RemoteAddr is used (with the port
// stripped). The empty string is returned when neither source yields a
// usable value, which lets callers treat the result as "no IP available"
// and skip dependent work.
func ExtractSourceIP(c *gin.Context) string {
if c == nil || c.Request == nil {
return ""
}
if xff := c.GetHeader("X-Forwarded-For"); xff != "" {
first := xff
if idx := strings.IndexByte(first, ','); idx >= 0 {
first = first[:idx]
}
return strings.TrimSpace(first)
}
addr := c.Request.RemoteAddr
if host, _, err := net.SplitHostPort(addr); err == nil {
return host
}
return addr
}