ipservice.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package controller
  2. import (
  3. "fmt"
  4. "net"
  5. "net/http"
  6. "strings"
  7. "github.com/gorilla/mux"
  8. )
  9. func ipHandlers(r *mux.Router) {
  10. r.HandleFunc("/api/getip", http.HandlerFunc(getPublicIP)).Methods("GET")
  11. }
  12. func getPublicIP(w http.ResponseWriter, r *http.Request) {
  13. r.Header.Set("Connection", "close")
  14. ip, err := parseIP(r)
  15. if err != nil {
  16. w.WriteHeader(400)
  17. if ip != "" {
  18. w.Write([]byte("ip is invalid: " + ip))
  19. return
  20. } else {
  21. w.Write([]byte("no ip found"))
  22. return
  23. }
  24. } else {
  25. if err != nil {
  26. fmt.Println(err)
  27. }
  28. }
  29. w.WriteHeader(200)
  30. w.Write([]byte(ip))
  31. }
  32. func parseIP(r *http.Request) (string, error) {
  33. // Get Public IP from header
  34. ip := r.Header.Get("X-REAL-IP")
  35. ipnet := net.ParseIP(ip)
  36. if ipnet != nil && !ipIsPrivate(ipnet) {
  37. return ip, nil
  38. }
  39. // If above fails, get Public IP from other header instead
  40. forwardips := r.Header.Get("X-FORWARDED-FOR")
  41. iplist := strings.Split(forwardips, ",")
  42. for _, ip := range iplist {
  43. ipnet := net.ParseIP(ip)
  44. if ipnet != nil && !ipIsPrivate(ipnet) {
  45. return ip, nil
  46. }
  47. }
  48. // If above also fails, get Public IP from Remote Address of request
  49. ip, _, err := net.SplitHostPort(r.RemoteAddr)
  50. if err != nil {
  51. return "", err
  52. }
  53. ipnet = net.ParseIP(ip)
  54. if ipnet != nil {
  55. if ipIsPrivate(ipnet) {
  56. return ip, fmt.Errorf("ip is a private address")
  57. }
  58. return ip, nil
  59. }
  60. return "", fmt.Errorf("no ip found")
  61. }
  62. func ipIsPrivate(ipnet net.IP) bool {
  63. return ipnet.IsPrivate() || ipnet.IsLoopback()
  64. }