Some checks failed
CI / build-and-test (push) Failing after -32m45s
* Include tool name from request in access log entries * Update user agent header in HTTP requests * Add tests for MCP tool name logging
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package requestip
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// FromRequest returns the best-effort client IP/host for a request, preferring
|
|
// proxy headers before falling back to RemoteAddr.
|
|
//
|
|
// Header precedence:
|
|
// 1) X-Real-IP
|
|
// 2) X-Forwarded-For (first value)
|
|
// 3) Forwarded (for=...)
|
|
// 4) RemoteAddr (host part)
|
|
func FromRequest(r *http.Request) string {
|
|
if r == nil {
|
|
return ""
|
|
}
|
|
|
|
if v := firstAddressToken(r.Header.Get("X-Real-IP")); v != "" {
|
|
return stripPort(v)
|
|
}
|
|
if v := firstAddressToken(r.Header.Get("X-Forwarded-For")); v != "" {
|
|
return stripPort(v)
|
|
}
|
|
if v := forwardedForValue(r.Header.Get("Forwarded")); v != "" {
|
|
return stripPort(v)
|
|
}
|
|
return stripPort(strings.TrimSpace(r.RemoteAddr))
|
|
}
|
|
|
|
func firstAddressToken(v string) string {
|
|
if v == "" {
|
|
return ""
|
|
}
|
|
part := strings.TrimSpace(strings.Split(v, ",")[0])
|
|
part = strings.Trim(part, `"`)
|
|
return strings.TrimSpace(part)
|
|
}
|
|
|
|
func forwardedForValue(v string) string {
|
|
for _, part := range strings.Split(v, ",") {
|
|
for _, kv := range strings.Split(part, ";") {
|
|
k, raw, ok := strings.Cut(strings.TrimSpace(kv), "=")
|
|
if !ok || !strings.EqualFold(strings.TrimSpace(k), "for") {
|
|
continue
|
|
}
|
|
candidate := strings.Trim(strings.TrimSpace(raw), `"`)
|
|
if candidate == "" {
|
|
continue
|
|
}
|
|
return candidate
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func stripPort(addr string) string {
|
|
addr = strings.TrimSpace(addr)
|
|
if addr == "" {
|
|
return ""
|
|
}
|
|
// RFC 7239 quoted values may wrap IPv6 with brackets.
|
|
addr = strings.Trim(addr, "[]")
|
|
host, _, err := net.SplitHostPort(addr)
|
|
if err == nil {
|
|
return host
|
|
}
|
|
return addr
|
|
}
|