client_ip.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // Copyright 2018 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package request // import "miniflux.app/http/request"
  5. import (
  6. "net"
  7. "net/http"
  8. "strings"
  9. )
  10. func dropIPv6zone(address string) string {
  11. i := strings.IndexByte(address, '%')
  12. if i != -1 {
  13. address = address[:i]
  14. }
  15. return address
  16. }
  17. // FindClientIP returns client real IP address.
  18. func FindClientIP(r *http.Request) string {
  19. headers := []string{"X-Forwarded-For", "X-Real-Ip"}
  20. for _, header := range headers {
  21. value := r.Header.Get(header)
  22. if value != "" {
  23. addresses := strings.Split(value, ",")
  24. address := strings.TrimSpace(addresses[0])
  25. address = dropIPv6zone(address)
  26. if net.ParseIP(address) != nil {
  27. return address
  28. }
  29. }
  30. }
  31. // Fallback to TCP/IP source IP address.
  32. remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
  33. if err != nil {
  34. remoteIP = r.RemoteAddr
  35. }
  36. remoteIP = dropIPv6zone(remoteIP)
  37. // When listening on a Unix socket, RemoteAddr is empty.
  38. if remoteIP == "" {
  39. remoteIP = "127.0.0.1"
  40. }
  41. return remoteIP
  42. }