extractIPFromHeader returns the client IP from the given proxy header by walking the X-Forwarded-For chain from right to left and stripping trusted proxy IPs. When trusted proxies are configured, the rightmost non-trusted IP is returned; otherwise the first valid IP (left-to-right) is returned. When
(header string)
| 634 | // valid IP (left-to-right) is returned. When IP validation is disabled, the raw header |
| 635 | // value is returned as-is. |
| 636 | func (r *DefaultReq) extractIPFromHeader(header string) string { |
| 637 | app := r.c.app |
| 638 | |
| 639 | if !app.config.EnableIPValidation { |
| 640 | return r.Get(header) |
| 641 | } |
| 642 | |
| 643 | headerValue := r.Get(header) |
| 644 | hasTrustedProxyConfig := r.hasTrustedProxyConfig() |
| 645 | if !hasTrustedProxyConfig { |
| 646 | start := 0 |
| 647 | for { |
| 648 | end := start |
| 649 | for end < len(headerValue) && headerValue[end] != ',' { |
| 650 | end++ |
| 651 | } |
| 652 | |
| 653 | ipStr := utils.Trim(headerValue[start:end], ' ') |
| 654 | if isValidProxyIP(ipStr) { |
| 655 | return ipStr |
| 656 | } |
| 657 | if end == len(headerValue) { |
| 658 | break |
| 659 | } |
| 660 | start = end + 1 |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | var leftmostIP string |
| 665 | |
| 666 | for end := len(headerValue); end > 0; { |
| 667 | start := end |
| 668 | for start > 0 && headerValue[start-1] != ',' { |
| 669 | start-- |
| 670 | } |
| 671 | |
| 672 | ipStr := utils.Trim(headerValue[start:end], ' ') |
| 673 | if isValidProxyIP(ipStr) { |
| 674 | leftmostIP = ipStr |
| 675 | if !r.isTrustedProxyIP(ipStr) { |
| 676 | return ipStr |
| 677 | } |
| 678 | } |
| 679 | |
| 680 | if start == 0 { |
| 681 | break |
| 682 | } |
| 683 | end = start - 1 |
| 684 | } |
| 685 | |
| 686 | if leftmostIP != "" { |
| 687 | return leftmostIP |
| 688 | } |
| 689 | if ip := r.c.fasthttp.RemoteIP(); ip != nil { |
| 690 | return ip.String() |
| 691 | } |
| 692 | return "" |
| 693 | } |
no test coverage detected