1// Package ipify provides a single function for retrieving your computer's 2// public IP address from the ipify service: http://www.ipify.org 3package ipify 4 5import ( 6 "errors" 7 "github.com/jpillora/backoff" 8 "io/ioutil" 9 "net/http" 10 "strconv" 11 "time" 12) 13 14// GetIp queries the ipify service (http://www.ipify.org) to retrieve this 15// machine's public IP address. Returns your public IP address as a string, and 16// any error encountered. By default, this function will run using exponential 17// backoff -- if this function fails for any reason, the request will be retried 18// up to 3 times. 19// 20// Usage: 21// 22// package main 23// 24// import ( 25// "fmt" 26// "github.com/rdegges/go-ipify" 27// ) 28// 29// func main() { 30// ip, err := ipify.GetIp() 31// if err != nil { 32// fmt.Println("Couldn't get my IP address:", err) 33// } else { 34// fmt.Println("My IP address is:", ip) 35// } 36// } 37func GetIp() (string, error) { 38 b := &backoff.Backoff{ 39 Jitter: true, 40 } 41 client := &http.Client{} 42 43 req, err := http.NewRequest("GET", API_URI, nil) 44 if err != nil { 45 return "", errors.New("Received an invalid status code from ipify: 500. The service might be experiencing issues.") 46 } 47 48 req.Header.Add("User-Agent", USER_AGENT) 49 50 for tries := 0; tries < MAX_TRIES; tries++ { 51 resp, err := client.Do(req) 52 if err != nil { 53 d := b.Duration() 54 time.Sleep(d) 55 continue 56 } 57 58 defer resp.Body.Close() 59 60 ip, err := ioutil.ReadAll(resp.Body) 61 if err != nil { 62 return "", errors.New("Received an invalid status code from ipify: 500. The service might be experiencing issues.") 63 } 64 65 if resp.StatusCode != 200 { 66 return "", errors.New("Received an invalid status code from ipify: " + strconv.Itoa(resp.StatusCode) + ". The service might be experiencing issues.") 67 } 68 69 return string(ip), nil 70 } 71 72 return "", errors.New("The request failed because it wasn't able to reach the ipify service. This is most likely due to a networking error of some sort.") 73} 74