47 lines
1.1 KiB
Go
47 lines
1.1 KiB
Go
package util
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
type LocationResult struct {
|
|
Country string `json:"country"`
|
|
Region string `json:"regionName"`
|
|
City string `json:"city"`
|
|
}
|
|
|
|
func GetLocation(ip string) (LocationResult, error) {
|
|
var loc LocationResult
|
|
// Example using ipinfo.io free API
|
|
resp, err := http.Get("http://ip-api.com/json/" + ip + "?fields=25")
|
|
if err != nil {
|
|
return loc, err
|
|
}
|
|
defer resp.Body.Close()
|
|
json.NewDecoder(resp.Body).Decode(&loc)
|
|
return loc, nil
|
|
}
|
|
|
|
func GetClientIP(r *http.Request) string {
|
|
// This header will be set by ngrok to the original client IP
|
|
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
|
log.Printf("DEBUG: Getting IP from X-Forwarded-For: %s\n", xff)
|
|
// X-Forwarded-For: client, proxy1, proxy2, ...
|
|
ips := strings.Split(xff, ",")
|
|
if len(ips) > 0 {
|
|
return strings.TrimSpace(ips[0])
|
|
}
|
|
}
|
|
// Fallback to RemoteAddr (not the real client IP, but just in case)
|
|
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
log.Printf("DEBUG: Falling to request remote addr: %s (%s)\n", host, r.RemoteAddr)
|
|
if err != nil {
|
|
return r.RemoteAddr
|
|
}
|
|
return host
|
|
}
|