@@ -11,7 +11,7 @@ import (
11
11
)
12
12
13
13
const (
14
- freeGeoIPBaseURL = "https://api.freegeoip.app/json "
14
+ ipBaseBaseURL = "https://api.ipbase.com/v2 "
15
15
deleteExpiredCacheItemsInternal = 10 * time .Minute
16
16
)
17
17
@@ -24,36 +24,105 @@ type Config struct {
24
24
CacheTTL time.Duration
25
25
}
26
26
27
- // Geofence holds a freegeoip.app client, cache and user supplied config
27
+ // Geofence holds a ipbase.com client, cache and user supplied config
28
28
type Geofence struct {
29
- Cache * cache.Cache
30
- FreeGeoIPClient * resty.Client
29
+ Cache * cache.Cache
30
+ IPBaseClient * resty.Client
31
31
Config
32
32
Latitude float64
33
33
Longitude float64
34
34
}
35
35
36
- // FreeGeoIPResponse is the json response from freegeoip.app
37
- type FreeGeoIPResponse struct {
38
- IP string `json:"ip"`
39
- CountryCode string `json:"country_code"`
40
- CountryName string `json:"country_name"`
41
- RegionCode string `json:"region_code"`
42
- RegionName string `json:"region_name"`
43
- City string `json:"city"`
44
- ZipCode string `json:"zip_code"`
45
- TimeZone string `json:"time_zone"`
46
- Latitude float64 `json:"latitude"`
47
- Longitude float64 `json:"longitude"`
48
- MetroCode int `json:"metro_code"`
36
+ // ipBaseResponse is the json response from ipbase.com
37
+ type ipBaseResponse struct {
38
+ Data data `json:"data"`
49
39
}
50
40
51
- // FreeGeoIPError is the json response when there is an error from freegeoip.app
52
- type FreeGeoIPError struct {
41
+ type timezone struct {
42
+ Id string `json:"id"`
43
+ CurrentTime string `json:"current_time"`
44
+ Code string `json:"code"`
45
+ IDaylightSaving bool `json:"is_daylight_saving"`
46
+ GmtOffset int `json:"gmt_offset"`
47
+ }
48
+
49
+ type connection struct {
50
+ Organization string `json:"organization"`
51
+ Isp string `json:"isp"`
52
+ Asn int `json:"asn"`
53
+ }
54
+
55
+ type continent struct {
56
+ Code string `json:"code"`
57
+ Name string `json:"name"`
58
+ NameTranslated string `json:"name_translated"`
59
+ }
60
+
61
+ type currencies struct {
62
+ Symbol string `json:"symbol"`
63
+ Name string `json:"name"`
64
+ SymbolNative string `json:"symbol_native"`
65
+ Code string `json:"code"`
66
+ NamePlural string `json:"name_plural"`
67
+ DecimalDigits int `json:"decimal_digits"`
68
+ Rounding int `json:"rounding"`
69
+ }
70
+
71
+ type languages struct {
72
+ Name string `json:"name"`
73
+ NameNative string `json:"name_native"`
74
+ }
75
+ type country struct {
76
+ Alpha2 string `json:"alpha2"`
77
+ Alpha3 string `json:"alpha3"`
78
+ CallingCodes []string `json:"calling_codes"`
79
+ Currencies []currencies `json:"currencies"`
80
+ Emoji string `json:"emoji"`
81
+ Ioc string `json:"ioc"`
82
+ Languages []languages `json:"languages"`
83
+ Name string `json:"name"`
84
+ NameTranslated string `json:"name_translated"`
85
+ Timezones []string `json:"timezones"`
86
+ IsInEuropeanUnion bool `json:"is_in_european_union"`
87
+ }
88
+
89
+ type city struct {
90
+ Name string `json:"name"`
91
+ NameTranslated string `json:"name_translated"`
92
+ }
93
+
94
+ type region struct {
95
+ Fips interface {} `json:"fips"`
96
+ Alpha2 interface {} `json:"alpha2"`
97
+ Name string `json:"name"`
98
+ NameTranslated string `json:"name_translated"`
99
+ }
100
+
101
+ type location struct {
102
+ GeonamesID interface {} `json:"geonames_id"`
103
+ Region region `json:"region"`
104
+ Continent continent `json:"continent"`
105
+ City city `json:"city"`
106
+ Zip string `json:"zip"`
107
+ Country country `json:"country"`
108
+ Latitude float64 `json:"latitude"`
109
+ Longitude float64 `json:"longitude"`
110
+ }
111
+
112
+ type data struct {
113
+ Timezone timezone `json:"timezone"`
114
+ IP string `json:"ip"`
115
+ Type string `json:"type"`
116
+ Connection connection `json:"connection"`
117
+ Location location `json:"location"`
118
+ }
119
+
120
+ // IPBaseError is the json response when there is an error from ipbase.com
121
+ type IPBaseError struct {
53
122
Message string `json:"message"`
54
123
}
55
124
56
- func (e * FreeGeoIPError ) Error () string {
125
+ func (e * IPBaseError ) Error () string {
57
126
return e .Message
58
127
}
59
128
@@ -68,41 +137,42 @@ func validateIPAddress(ipAddress string) error {
68
137
return nil
69
138
}
70
139
71
- // getIPGeoData fetches geolocation data for specified IP address from https://freegeoip.app
72
- func (g * Geofence ) getIPGeoData (ipAddress string ) (* FreeGeoIPResponse , error ) {
73
- freeGeoIPResponse := & FreeGeoIPResponse {}
74
- freeGeoIPError := & FreeGeoIPError {}
140
+ // getIPGeoData fetches geolocation data for specified IP address from https://ipbase.com
141
+ func (g * Geofence ) getIPGeoData (ipAddress string ) (* ipBaseResponse , error ) {
142
+ response := & ipBaseResponse {}
143
+ ipBaseError := & IPBaseError {}
75
144
76
- resp , err := g .FreeGeoIPClient .R ().
145
+ resp , err := g .IPBaseClient .R ().
77
146
SetHeader ("Accept" , "application/json" ).
78
147
SetQueryParam ("apikey" , g .Token ).
79
- SetResult (freeGeoIPResponse ).
80
- SetError (freeGeoIPError ).
81
- Get (ipAddress )
148
+ SetQueryParam ("ip" , ipAddress ).
149
+ SetResult (response ).
150
+ SetError (ipBaseError ).
151
+ Get ("/info" )
82
152
if err != nil {
83
- return freeGeoIPResponse , err
153
+ return response , err
84
154
}
85
155
86
156
// If api gives back status code >399, report error to user
87
157
if resp .IsError () {
88
- return freeGeoIPResponse , freeGeoIPError
158
+ return response , ipBaseError
89
159
}
90
160
91
- return resp .Result ().(* FreeGeoIPResponse ), nil
161
+ return resp .Result ().(* ipBaseResponse ), nil
92
162
}
93
163
94
164
// New creates a new geofence for the IP address specified.
95
165
// Use "" as the ip address to geofence the machine your application is running on
96
- // Token comes from https://freegeoip.app /
166
+ // Token comes from https://ipbase.com /
97
167
func New (c * Config ) (* Geofence , error ) {
98
- // Create new client for freegeoip.app
99
- freeGeoIPClient := resty .New ().SetBaseURL (freeGeoIPBaseURL )
168
+ // Create new client for ipbase.com
169
+ IPBaseClient := resty .New ().SetBaseURL (ipBaseBaseURL )
100
170
101
171
// New Geofence object
102
172
geofence := & Geofence {
103
- Config : * c ,
104
- FreeGeoIPClient : freeGeoIPClient ,
105
- Cache : cache .New (c .CacheTTL , deleteExpiredCacheItemsInternal ),
173
+ Config : * c ,
174
+ IPBaseClient : IPBaseClient ,
175
+ Cache : cache .New (c .CacheTTL , deleteExpiredCacheItemsInternal ),
106
176
}
107
177
108
178
// Get current location of specified IP address
@@ -114,8 +184,8 @@ func New(c *Config) (*Geofence, error) {
114
184
}
115
185
116
186
// Set the location of our geofence to compare against looked up IP's
117
- geofence .Latitude = ipAddressLookupDetails .Latitude
118
- geofence .Longitude = ipAddressLookupDetails .Longitude
187
+ geofence .Latitude = ipAddressLookupDetails .Data . Location . Latitude
188
+ geofence .Longitude = ipAddressLookupDetails .Data . Location . Longitude
119
189
120
190
return geofence , nil
121
191
}
@@ -148,7 +218,7 @@ func (g *Geofence) IsIPAddressNear(ipAddress string) (bool, error) {
148
218
149
219
// Format our IP coordinates and the clients
150
220
currentCoordinates := geo .NewCoordinatesFromDegrees (g .Latitude , g .Longitude )
151
- clientCoordinates := geo .NewCoordinatesFromDegrees (ipAddressLookupDetails .Latitude , ipAddressLookupDetails .Longitude )
221
+ clientCoordinates := geo .NewCoordinatesFromDegrees (ipAddressLookupDetails .Data . Location . Latitude , ipAddressLookupDetails . Data . Location .Longitude )
152
222
153
223
// Get distance in kilometers
154
224
distance := currentCoordinates .Distance (clientCoordinates )
0 commit comments