Skip to content

Merge remote-tracking branch 'origin/TT-14891/dynamic-xff-client-ip' …

2c0ec8a
Select commit
Loading
Failed to load commit list.
Merged

TT-14891 - adds client ip from XFF by depth #7063

Merge remote-tracking branch 'origin/TT-14891/dynamic-xff-client-ip' …
2c0ec8a
Select commit
Loading
Failed to load commit list.
probelabs / Visor: performance succeeded Nov 3, 2025 in 3m 54s

✅ Check Passed (Warnings Found)

performance check passed. Found 1 warning, but fail_if condition was not met.

Details

📊 Summary

  • Total Issues: 1
  • Warning Issues: 1

🐛 Issues by Category

⚡ Performance (1)

  • ⚠️ request/real_ip.go:28 - The RealIP function's new implementation for parsing the X-Forwarded-For header uses strings.Split for all cases. This function allocates a new slice and strings for each IP address in the header on every request. This introduces a performance regression compared to the previous, more efficient implementation which used strings.IndexByte for the default case of selecting the first IP. For requests with a long chain of proxies in the X-Forwarded-For header, this can lead to a noticeable increase in memory allocations and garbage collector pressure on a critical request path.

Powered by Visor from Probelabs

💡 TIP: You can chat with Visor using /visor ask <your question>

Annotations

Check warning on line 28 in request/real_ip.go

See this annotation in the file changed.

@probelabs probelabs / Visor: performance

performance Issue

The `RealIP` function's new implementation for parsing the `X-Forwarded-For` header uses `strings.Split` for all cases. This function allocates a new slice and strings for each IP address in the header on every request. This introduces a performance regression compared to the previous, more efficient implementation which used `strings.IndexByte` for the default case of selecting the first IP. For requests with a long chain of proxies in the `X-Forwarded-For` header, this can lead to a noticeable increase in memory allocations and garbage collector pressure on a critical request path.
Raw output
To mitigate the performance impact, optimize for the default case (`XFFDepth` is 0) by reverting to the more performant logic of using `strings.IndexByte` to find the first comma and then slicing the string. This avoids the overhead of `strings.Split` for the most common configuration and prevents a performance regression. The `strings.Split` logic should only be used when `XFFDepth > 0`.

**Example:**
```go
// ...
depth := 0
if Global != nil {
    depth = Global().HttpServerOptions.XFFDepth
}

if fw := r.Header.Get(header.XForwardFor); fw != "" {
    var ip string
    if depth == 0 {
        // Optimized path for default case
        if i := strings.IndexByte(fw, ','); i >= 0 {
            ip = fw[:i]
        } else {
            ip = fw
        }
    } else {
        // Path for new functionality
        xffs := strings.Split(fw, ",")
        if depth > len(xffs) {
            return ""
        }
        ip = xffs[len(xffs)-depth]
    }

    ip = strings.TrimSpace(ip)
    if parsedIP := net.ParseIP(ip); parsedIP != nil {
        return parsedIP.String()
    }
    // If IP is invalid, fall through to use RemoteAddr
}
// ...
```