-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
150 lines (118 loc) · 2.6 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package geoip
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"sync"
"time"
)
type Client struct {
Debug bool
IPStackApiKey string
LastLookup *IP
}
func New() *Client {
return &Client{
IPStackApiKey: os.Getenv("IPSTACK_API_KEY"),
}
}
// Lookup takes a string based IPv4 address and queries for location and ISP info.
func (self *Client) Lookup(ipQuery string) (IP, error) {
ip := IP{}
var err error
funcs := []func(ip *IP){
// freegeoip.net
func(ip *IP) {
ipStack := IPStackResult{}
var debug DebugResult
debug, err = self.call(
fmt.Sprintf("http://api.ipstack.com/%s?access_key=%s", ipQuery, self.IPStackApiKey),
&ipStack,
)
if err != nil {
fmt.Println("error", err)
return
}
ip.IP = ipStack.IP
ip.CountryName = ipStack.CountryName
ip.CountryCode = ipStack.CountryCode
ip.RegionName = ipStack.RegionName
ip.RegionCode = ipStack.RegionCode
ip.City = ipStack.City
ip.ZipCode = ipStack.ZipCode
ip.Timezone = ipStack.Timezone
ip.Latitude = ipStack.Latitude
ip.Longitude = ipStack.Longitude
ip.Timezone = ipStack.Timezone
ip.Location = ipStack.Location
ip.Currency = ipStack.Currency
ip.MetroCode = ipStack.MetroCode
if self.Debug {
fmt.Println("debug freegeoip", debug, ipStack)
}
},
// ip-api.com
func(ip *IP) {
ipApi := IPApiResult{}
var debug DebugResult
debug, err = self.call(
"http://ip-api.com/json/"+ipQuery,
&ipApi,
)
if err != nil {
fmt.Println("error", err)
return
}
ip.ISP = ipApi.ISP
ip.As = ipApi.As
ip.Org = ipApi.Org
if self.Debug {
fmt.Println("debug ip-api", debug, ipApi)
}
},
}
wg := new(sync.WaitGroup)
wg.Add(len(funcs))
for _, fn := range funcs {
go func(f func(ip *IP)) {
f(&ip)
wg.Done()
}(fn)
}
wg.Wait()
if self.Debug {
fmt.Println("IP", ip, err)
}
return ip, err
}
// Call uses basic (GET) method to make a request to the API
func (self *Client) call(apiUrl string, result interface{}) (DebugResult, error) {
fmt.Println("call", apiUrl)
timeout := time.Duration(10 * time.Second)
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(apiUrl)
if err != nil {
return DebugResult{}, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return DebugResult{}, err
}
debug := DebugResult{
RequestedURL: apiUrl,
Status: resp.Status,
StatusCode: resp.StatusCode,
RawResponse: body,
}
fmt.Println("body", string(body))
err = json.Unmarshal(body, &result)
if err != nil {
return debug, err
}
return debug, err
}