client_ip.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  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. // FindClientIP returns the client real IP address based on trusted Reverse-Proxy HTTP headers.
  11. func FindClientIP(r *http.Request) string {
  12. headers := []string{"X-Forwarded-For", "X-Real-Ip"}
  13. for _, header := range headers {
  14. value := r.Header.Get(header)
  15. if value != "" {
  16. addresses := strings.Split(value, ",")
  17. address := strings.TrimSpace(addresses[0])
  18. address = dropIPv6zone(address)
  19. if net.ParseIP(address) != nil {
  20. return address
  21. }
  22. }
  23. }
  24. // Fallback to TCP/IP source IP address.
  25. return FindRemoteIP(r)
  26. }
  27. // FindRemoteIP returns remote client IP address.
  28. func FindRemoteIP(r *http.Request) string {
  29. remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
  30. if err != nil {
  31. remoteIP = r.RemoteAddr
  32. }
  33. remoteIP = dropIPv6zone(remoteIP)
  34. // When listening on a Unix socket, RemoteAddr is empty.
  35. if remoteIP == "" {
  36. remoteIP = "127.0.0.1"
  37. }
  38. return remoteIP
  39. }
  40. func dropIPv6zone(address string) string {
  41. i := strings.IndexByte(address, '%')
  42. if i != -1 {
  43. address = address[:i]
  44. }
  45. return address
  46. }