func()

in remoteip/parser.go [50:102]


func (p *RemoteIPParser) GetIP(r *http.Request) (string, error) {
	// Get the direct remote address (equivalent to REMOTE_ADDR in Rails)
	remoteAddr := p.parseIP(r.RemoteAddr)

	// Get IPs from X-Forwarded-For header(s)
	// In Go, r.Header.Get() returns joined values if there are multiple headers with the same name
	forwardedIPs := p.parseIPsFromHeader(r.Header.Get("X-Forwarded-For"))

	// Get IPs from Client-IP header(s)
	clientIPs := p.parseIPsFromHeader(r.Header.Get("Client-Ip"))

	// Check for potential IP spoofing if both headers are present
	if p.CheckIPSpoofing && len(clientIPs) > 0 && len(forwardedIPs) > 0 {
		// If the last client IP is not in the forwarded IPs list, it might be spoofing
		lastClientIP := clientIPs[len(clientIPs)-1]
		isInForwardedIPs := false
		for _, ip := range forwardedIPs {
			if ip == lastClientIP {
				isInForwardedIPs = true
				break
			}
		}

		if !isInForwardedIPs {
			return "", ErrIPSpoofAttack
		}
	}

	// Following Rails logic:
	// 1. Combine forwarded and client IPs (in original order)
	// 2. Check for non-proxies in the combined list
	// 3. If all IPs are proxies, use the furthest away IP (last in the list)

	// Combine IPs from headers (in original order)
	ips := make([]string, 0, len(forwardedIPs)+len(clientIPs))
	ips = append(ips, forwardedIPs...)
	ips = append(ips, clientIPs...)

	// Filter out trusted proxies
	filteredIPs := p.filterProxies(append(ips, remoteAddr))
	if len(filteredIPs) > 0 {
		return filteredIPs[0], nil
	}

	// If all IPs are trusted proxies, return the "furthest away" IP
	// (which is the last IP in the list after filtering)
	if len(ips) > 0 {
		return ips[len(ips)-1], nil
	}

	// Final fallback is the remote address
	return remoteAddr, nil
}