feat(cli): add verbose logging option for CLI commands
Some checks failed
CI / build-and-test (push) Failing after -32m43s
Some checks failed
CI / build-and-test (push) Failing after -32m43s
* Introduced a new flag `--verbose` to enable detailed logging. * Implemented logging for connection events in SSE and stdio commands. * Added a utility function to handle verbose logging.
This commit is contained in:
76
internal/requestip/requestip.go
Normal file
76
internal/requestip/requestip.go
Normal file
@@ -0,0 +1,76 @@
|
||||
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-Host
|
||||
// 3) X-Forwarded-For (first value)
|
||||
// 4) Forwarded (for=...)
|
||||
// 5) 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-Host")); 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
|
||||
}
|
||||
Reference in New Issue
Block a user