geocoder 1.4.9 → 1.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +60 -0
- data/LICENSE +1 -1
- data/README.md +350 -979
- data/bin/console +13 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +1 -1
- data/lib/geocoder/cache.rb +4 -0
- data/lib/geocoder/calculations.rb +1 -1
- data/lib/geocoder/cli.rb +2 -2
- data/lib/geocoder/configuration.rb +3 -2
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/exceptions.rb +1 -1
- data/lib/geocoder/ip_address.rb +16 -2
- data/lib/geocoder/lookup.rb +9 -5
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amap.rb +7 -3
- data/lib/geocoder/lookups/baidu.rb +14 -10
- data/lib/geocoder/lookups/baidu_ip.rb +7 -36
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +18 -5
- data/lib/geocoder/lookups/base.rb +27 -4
- data/lib/geocoder/lookups/bing.rb +10 -13
- data/lib/geocoder/lookups/db_ip_com.rb +9 -6
- data/lib/geocoder/lookups/dstk.rb +4 -2
- data/lib/geocoder/lookups/esri.rb +44 -28
- data/lib/geocoder/lookups/freegeoip.rb +11 -7
- data/lib/geocoder/lookups/geocoder_ca.rb +4 -4
- data/lib/geocoder/lookups/geocodio.rb +5 -5
- data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
- data/lib/geocoder/lookups/google.rb +15 -10
- data/lib/geocoder/lookups/google_places_details.rb +11 -17
- data/lib/geocoder/lookups/google_places_search.rb +30 -4
- data/lib/geocoder/lookups/google_premier.rb +14 -0
- data/lib/geocoder/lookups/here.rb +29 -23
- data/lib/geocoder/lookups/ip2location.rb +67 -0
- data/lib/geocoder/lookups/ipapi_com.rb +9 -13
- data/lib/geocoder/lookups/ipdata_co.rb +9 -4
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +11 -29
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +11 -12
- data/lib/geocoder/lookups/latlon.rb +5 -6
- data/lib/geocoder/lookups/location_iq.rb +10 -4
- data/lib/geocoder/lookups/mapbox.rb +7 -6
- data/lib/geocoder/lookups/mapquest.rb +4 -5
- data/lib/geocoder/lookups/maxmind.rb +6 -6
- data/lib/geocoder/lookups/maxmind_geoip2.rb +8 -7
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/nominatim.rb +4 -4
- data/lib/geocoder/lookups/opencagedata.rb +6 -5
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +8 -9
- data/lib/geocoder/lookups/pickpoint.rb +9 -3
- data/lib/geocoder/lookups/pointpin.rb +10 -9
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
- data/lib/geocoder/lookups/postcodes_io.rb +6 -3
- data/lib/geocoder/lookups/smarty_streets.rb +26 -11
- data/lib/geocoder/lookups/telize.rb +24 -4
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +7 -8
- data/lib/geocoder/query.rb +14 -0
- data/lib/geocoder/railtie.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/baidu.rb +10 -14
- data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
- data/lib/geocoder/results/base.rb +13 -1
- data/lib/geocoder/results/bing.rb +1 -1
- data/lib/geocoder/results/db_ip_com.rb +1 -6
- data/lib/geocoder/results/freegeoip.rb +0 -5
- data/lib/geocoder/results/geocoder_ca.rb +3 -3
- data/lib/geocoder/results/geoip2.rb +0 -4
- data/lib/geocoder/results/geoportail_lu.rb +5 -3
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipdata_co.rb +0 -5
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/maxmind.rb +0 -5
- data/lib/geocoder/results/maxmind_local.rb +0 -5
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +4 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/smarty_streets.rb +48 -18
- data/lib/geocoder/results/telize.rb +0 -5
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +1 -1
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +217 -59
- data/lib/geocoder/sql.rb +4 -4
- data/lib/geocoder/stores/active_record.rb +1 -3
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +3 -3
- metadata +27 -23
- data/lib/geocoder/lookups/geocoder_us.rb +0 -43
- data/lib/geocoder/lookups/mapzen.rb +0 -15
- data/lib/geocoder/lookups/okf.rb +0 -44
- data/lib/geocoder/lookups/ovi.rb +0 -62
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/mapzen.rb +0 -5
- data/lib/geocoder/results/okf.rb +0 -106
- data/lib/geocoder/results/ovi.rb +0 -71
- data/lib/hash_recursive_merge.rb +0 -74
|
@@ -8,12 +8,12 @@ module Geocoder::Lookup
|
|
|
8
8
|
"Geocoder.ca"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def query_url(query)
|
|
12
|
-
"#{protocol}://geocoder.ca/?" + url_query_string(query)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
11
|
private # ---------------------------------------------------------------
|
|
16
12
|
|
|
13
|
+
def base_query_url(query)
|
|
14
|
+
"#{protocol}://geocoder.ca/?"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
17
|
def results(query)
|
|
18
18
|
return [] unless doc = fetch_data(query)
|
|
19
19
|
if doc['error'].nil?
|
|
@@ -8,11 +8,6 @@ module Geocoder::Lookup
|
|
|
8
8
|
"Geocodio"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def query_url(query)
|
|
12
|
-
path = query.reverse_geocode? ? "reverse" : "geocode"
|
|
13
|
-
"#{protocol}://api.geocod.io/v1.3/#{path}?#{url_query_string(query)}"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
11
|
def results(query)
|
|
17
12
|
return [] unless doc = fetch_data(query)
|
|
18
13
|
return doc["results"] if doc['error'].nil?
|
|
@@ -32,6 +27,11 @@ module Geocoder::Lookup
|
|
|
32
27
|
|
|
33
28
|
private # ---------------------------------------------------------------
|
|
34
29
|
|
|
30
|
+
def base_query_url(query)
|
|
31
|
+
path = query.reverse_geocode? ? "reverse" : "geocode"
|
|
32
|
+
"#{protocol}://api.geocod.io/v1.6/#{path}?"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
35
|
def query_url_params(query)
|
|
36
36
|
{
|
|
37
37
|
:api_key => configuration.api_key,
|
|
@@ -9,14 +9,14 @@ module Geocoder
|
|
|
9
9
|
"Geoportail.lu"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
url_base_path(query) + url_query_string(query)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private
|
|
12
|
+
private # ---------------------------------------------------------------
|
|
17
13
|
|
|
18
|
-
def
|
|
19
|
-
query.reverse_geocode?
|
|
14
|
+
def base_query_url(query)
|
|
15
|
+
if query.reverse_geocode?
|
|
16
|
+
reverse_geocode_url_base_path
|
|
17
|
+
else
|
|
18
|
+
search_url_base_path
|
|
19
|
+
end
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def search_url_base_path
|
|
@@ -21,12 +21,12 @@ module Geocoder::Lookup
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def query_url(query)
|
|
25
|
-
"#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + url_query_string(query)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
24
|
private # ---------------------------------------------------------------
|
|
29
25
|
|
|
26
|
+
def base_query_url(query)
|
|
27
|
+
"#{protocol}://maps.googleapis.com/maps/api/geocode/json?"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
30
|
def configure_ssl!(client)
|
|
31
31
|
client.instance_eval {
|
|
32
32
|
@ssl_context = OpenSSL::SSL::SSLContext.new
|
|
@@ -44,19 +44,24 @@ module Geocoder::Lookup
|
|
|
44
44
|
super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def result_root_attr
|
|
48
|
+
'results'
|
|
49
|
+
end
|
|
50
|
+
|
|
47
51
|
def results(query)
|
|
48
52
|
return [] unless doc = fetch_data(query)
|
|
49
|
-
case doc['status']
|
|
50
|
-
|
|
53
|
+
case doc['status']
|
|
54
|
+
when "OK" # OK status implies >0 results
|
|
55
|
+
return doc[result_root_attr]
|
|
51
56
|
when "OVER_QUERY_LIMIT"
|
|
52
57
|
raise_error(Geocoder::OverQueryLimitError) ||
|
|
53
58
|
Geocoder.log(:warn, "#{name} API error: over query limit.")
|
|
54
59
|
when "REQUEST_DENIED"
|
|
55
|
-
raise_error(Geocoder::RequestDenied) ||
|
|
56
|
-
Geocoder.log(:warn, "#{name} API error: request denied.")
|
|
60
|
+
raise_error(Geocoder::RequestDenied, doc['error_message']) ||
|
|
61
|
+
Geocoder.log(:warn, "#{name} API error: request denied (#{doc['error_message']}).")
|
|
57
62
|
when "INVALID_REQUEST"
|
|
58
|
-
raise_error(Geocoder::InvalidRequest) ||
|
|
59
|
-
Geocoder.log(:warn, "#{name} API error: invalid request.")
|
|
63
|
+
raise_error(Geocoder::InvalidRequest, doc['error_message']) ||
|
|
64
|
+
Geocoder.log(:warn, "#{name} API error: invalid request (#{doc['error_message']}).")
|
|
60
65
|
end
|
|
61
66
|
return []
|
|
62
67
|
end
|
|
@@ -16,27 +16,21 @@ module Geocoder
|
|
|
16
16
|
[:https]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
"#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
|
|
21
23
|
end
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
def result_root_attr
|
|
26
|
+
'result'
|
|
27
|
+
end
|
|
24
28
|
|
|
25
29
|
def results(query)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return [doc["result"]]
|
|
31
|
-
when "OVER_QUERY_LIMIT"
|
|
32
|
-
raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
|
|
33
|
-
when "REQUEST_DENIED"
|
|
34
|
-
raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
|
|
35
|
-
when "INVALID_REQUEST"
|
|
36
|
-
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
[]
|
|
30
|
+
result = super(query)
|
|
31
|
+
return [result] unless result.is_a? Array
|
|
32
|
+
|
|
33
|
+
result
|
|
40
34
|
end
|
|
41
35
|
|
|
42
36
|
def query_url_google_params(query)
|
|
@@ -16,18 +16,44 @@ module Geocoder
|
|
|
16
16
|
[:https]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def result_root_attr
|
|
22
|
+
'candidates'
|
|
21
23
|
end
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
def base_query_url(query)
|
|
26
|
+
"#{protocol}://maps.googleapis.com/maps/api/place/findplacefromtext/json?"
|
|
27
|
+
end
|
|
24
28
|
|
|
25
29
|
def query_url_google_params(query)
|
|
26
30
|
{
|
|
27
|
-
|
|
31
|
+
input: query.text,
|
|
32
|
+
inputtype: 'textquery',
|
|
33
|
+
fields: fields(query),
|
|
28
34
|
language: query.language || configuration.language
|
|
29
35
|
}
|
|
30
36
|
end
|
|
37
|
+
|
|
38
|
+
def fields(query)
|
|
39
|
+
query_fields = query.options[:fields]
|
|
40
|
+
return format_fields(query_fields) if query_fields
|
|
41
|
+
|
|
42
|
+
default_fields
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_fields
|
|
46
|
+
legacy = %w[id reference]
|
|
47
|
+
basic = %w[business_status formatted_address geometry icon name
|
|
48
|
+
photos place_id plus_code types]
|
|
49
|
+
contact = %w[opening_hours]
|
|
50
|
+
atmosphere = %W[price_level rating user_ratings_total]
|
|
51
|
+
format_fields(legacy, basic, contact, atmosphere)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def format_fields(*fields)
|
|
55
|
+
fields.flatten.join(',')
|
|
56
|
+
end
|
|
31
57
|
end
|
|
32
58
|
end
|
|
33
59
|
end
|
|
@@ -21,6 +21,20 @@ module Geocoder::Lookup
|
|
|
21
21
|
|
|
22
22
|
private # ---------------------------------------------------------------
|
|
23
23
|
|
|
24
|
+
def result_root_attr
|
|
25
|
+
'results'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cache_key(query)
|
|
29
|
+
"#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + hash_to_query(cache_key_params(query))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def cache_key_params(query)
|
|
33
|
+
query_url_google_params(query).merge(super).reject do |k,v|
|
|
34
|
+
[:key, :client, :channel].include?(k)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
24
38
|
def query_url_params(query)
|
|
25
39
|
query_url_google_params(query).merge(super).merge(
|
|
26
40
|
:key => nil, # don't use param inherited from Google lookup
|
|
@@ -9,15 +9,19 @@ module Geocoder::Lookup
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def required_api_key_parts
|
|
12
|
-
[
|
|
12
|
+
['api_key']
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def
|
|
16
|
-
|
|
15
|
+
def supported_protocols
|
|
16
|
+
[:https]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private # ---------------------------------------------------------------
|
|
20
20
|
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
"#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
def results(query)
|
|
22
26
|
return [] unless doc = fetch_data(query)
|
|
23
27
|
return [] unless doc['Response'] && doc['Response']['View']
|
|
@@ -28,34 +32,36 @@ module Geocoder::Lookup
|
|
|
28
32
|
[]
|
|
29
33
|
end
|
|
30
34
|
|
|
31
|
-
def
|
|
35
|
+
def query_url_here_options(query, reverse_geocode)
|
|
32
36
|
options = {
|
|
33
|
-
:
|
|
34
|
-
:
|
|
35
|
-
:
|
|
37
|
+
gen: 9,
|
|
38
|
+
apikey: configuration.api_key,
|
|
39
|
+
language: (query.language || configuration.language)
|
|
36
40
|
}
|
|
41
|
+
if reverse_geocode
|
|
42
|
+
options[:mode] = :retrieveAddresses
|
|
43
|
+
return options
|
|
44
|
+
end
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
:prox=>query.sanitized_text,
|
|
41
|
-
:mode=>:retrieveAddresses
|
|
42
|
-
)
|
|
43
|
-
else
|
|
44
|
-
super.merge(options).merge(
|
|
45
|
-
:searchtext=>query.sanitized_text
|
|
46
|
-
)
|
|
46
|
+
unless (country = query.options[:country]).nil?
|
|
47
|
+
options[:country] = country
|
|
47
48
|
end
|
|
48
|
-
end
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return a.first if a.is_a?(Array)
|
|
50
|
+
unless (mapview = query.options[:bounds]).nil?
|
|
51
|
+
options[:mapview] = mapview.map{ |point| "%f,%f" % point }.join(';')
|
|
53
52
|
end
|
|
53
|
+
options
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def
|
|
57
|
-
if
|
|
58
|
-
|
|
56
|
+
def query_url_params(query)
|
|
57
|
+
if query.reverse_geocode?
|
|
58
|
+
super.merge(query_url_here_options(query, true)).merge(
|
|
59
|
+
prox: query.sanitized_text
|
|
60
|
+
)
|
|
61
|
+
else
|
|
62
|
+
super.merge(query_url_here_options(query, false)).merge(
|
|
63
|
+
searchtext: query.sanitized_text
|
|
64
|
+
)
|
|
59
65
|
end
|
|
60
66
|
end
|
|
61
67
|
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/ip2location'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Ip2location < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"IP2LocationApi"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def supported_protocols
|
|
12
|
+
[:http, :https]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private # ----------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
def base_query_url(query)
|
|
18
|
+
"#{protocol}://api.ip2location.com/?"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def query_url_params(query)
|
|
22
|
+
params = super
|
|
23
|
+
if configuration.has_key?(:package)
|
|
24
|
+
params.merge!(package: configuration[:package])
|
|
25
|
+
end
|
|
26
|
+
params
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def results(query)
|
|
30
|
+
# don't look up a loopback or private address, just return the stored result
|
|
31
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
|
32
|
+
return [] unless doc = fetch_data(query)
|
|
33
|
+
if doc["response"] == "INVALID ACCOUNT"
|
|
34
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT")
|
|
35
|
+
return []
|
|
36
|
+
else
|
|
37
|
+
return [doc]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reserved_result(query)
|
|
42
|
+
{
|
|
43
|
+
"country_code" => "INVALID IP ADDRESS",
|
|
44
|
+
"country_name" => "INVALID IP ADDRESS",
|
|
45
|
+
"region_name" => "INVALID IP ADDRESS",
|
|
46
|
+
"city_name" => "INVALID IP ADDRESS",
|
|
47
|
+
"latitude" => "INVALID IP ADDRESS",
|
|
48
|
+
"longitude" => "INVALID IP ADDRESS",
|
|
49
|
+
"zip_code" => "INVALID IP ADDRESS",
|
|
50
|
+
"time_zone" => "INVALID IP ADDRESS",
|
|
51
|
+
"isp" => "INVALID IP ADDRESS",
|
|
52
|
+
"domain" => "INVALID IP ADDRESS",
|
|
53
|
+
"net_speed" => "INVALID IP ADDRESS",
|
|
54
|
+
"idd_code" => "INVALID IP ADDRESS",
|
|
55
|
+
"area_code" => "INVALID IP ADDRESS",
|
|
56
|
+
"weather_station_code" => "INVALID IP ADDRESS",
|
|
57
|
+
"weather_station_name" => "INVALID IP ADDRESS",
|
|
58
|
+
"mcc" => "INVALID IP ADDRESS",
|
|
59
|
+
"mnc" => "INVALID IP ADDRESS",
|
|
60
|
+
"mobile_brand" => "INVALID IP ADDRESS",
|
|
61
|
+
"elevation" => "INVALID IP ADDRESS",
|
|
62
|
+
"usage_type" => "INVALID IP ADDRESS"
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -8,17 +8,6 @@ module Geocoder::Lookup
|
|
|
8
8
|
"ip-api.com"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def query_url(query)
|
|
12
|
-
domain = configuration.api_key ? "pro.ip-api.com" : "ip-api.com"
|
|
13
|
-
url_ = "#{protocol}://#{domain}/json/#{query.sanitized_text}"
|
|
14
|
-
|
|
15
|
-
if (params = url_query_string(query)) && !params.empty?
|
|
16
|
-
url_ + "?" + params
|
|
17
|
-
else
|
|
18
|
-
url_
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
11
|
def supported_protocols
|
|
23
12
|
if configuration.api_key
|
|
24
13
|
[:http, :https]
|
|
@@ -27,8 +16,14 @@ module Geocoder::Lookup
|
|
|
27
16
|
end
|
|
28
17
|
end
|
|
29
18
|
|
|
19
|
+
private # ----------------------------------------------------------------
|
|
30
20
|
|
|
31
|
-
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
domain = configuration.api_key ? "pro.ip-api.com" : "ip-api.com"
|
|
23
|
+
url = "#{protocol}://#{domain}/json/#{query.sanitized_text}"
|
|
24
|
+
url << "?" if not url_query_string(query).empty?
|
|
25
|
+
url
|
|
26
|
+
end
|
|
32
27
|
|
|
33
28
|
def parse_raw_data(raw_data)
|
|
34
29
|
if raw_data.chomp == "invalid key"
|
|
@@ -39,7 +34,8 @@ module Geocoder::Lookup
|
|
|
39
34
|
end
|
|
40
35
|
|
|
41
36
|
def results(query)
|
|
42
|
-
return
|
|
37
|
+
# don't look up a loopback or private address, just return the stored result
|
|
38
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
|
43
39
|
|
|
44
40
|
return [] unless doc = fetch_data(query)
|
|
45
41
|
|
|
@@ -13,15 +13,20 @@ module Geocoder::Lookup
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def query_url(query)
|
|
16
|
-
|
|
16
|
+
# Ipdata.co requires that the API key be sent as a query parameter.
|
|
17
|
+
# It no longer supports API keys sent as headers.
|
|
18
|
+
"#{protocol}://#{host}/#{query.sanitized_text}?api-key=#{configuration.api_key}"
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
private # ---------------------------------------------------------------
|
|
20
22
|
|
|
23
|
+
def cache_key(query)
|
|
24
|
+
query_url(query)
|
|
25
|
+
end
|
|
26
|
+
|
|
21
27
|
def results(query)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return [reserved_result(query.text)] if query.loopback_ip_address?
|
|
28
|
+
# don't look up a loopback or private address, just return the stored result
|
|
29
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
|
25
30
|
# note: Ipdata.co returns plain text on bad request
|
|
26
31
|
(doc = fetch_data(query)) ? [doc] : []
|
|
27
32
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/ipgeolocation'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module Geocoder::Lookup
|
|
6
|
+
class Ipgeolocation < Base
|
|
7
|
+
|
|
8
|
+
ERROR_CODES = {
|
|
9
|
+
400 => Geocoder::RequestDenied, # subscription is paused
|
|
10
|
+
401 => Geocoder::InvalidApiKey, # missing/invalid API key
|
|
11
|
+
403 => Geocoder::InvalidRequest, # invalid IP address
|
|
12
|
+
404 => Geocoder::InvalidRequest, # not found
|
|
13
|
+
423 => Geocoder::InvalidRequest # bogon/reserved IP address
|
|
14
|
+
}
|
|
15
|
+
ERROR_CODES.default = Geocoder::Error
|
|
16
|
+
|
|
17
|
+
def name
|
|
18
|
+
"Ipgeolocation"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def supported_protocols
|
|
22
|
+
[:https]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private # ----------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
def base_query_url(query)
|
|
28
|
+
"#{protocol}://api.ipgeolocation.io/ipgeo?"
|
|
29
|
+
end
|
|
30
|
+
def query_url_params(query)
|
|
31
|
+
{
|
|
32
|
+
ip: query.sanitized_text,
|
|
33
|
+
apiKey: configuration.api_key
|
|
34
|
+
}.merge(super)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def results(query)
|
|
38
|
+
# don't look up a loopback or private address, just return the stored result
|
|
39
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
|
40
|
+
[fetch_data(query)]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def reserved_result(ip)
|
|
44
|
+
{
|
|
45
|
+
"ip" => ip,
|
|
46
|
+
"country_name" => "Reserved",
|
|
47
|
+
"country_code2" => "RD"
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|