geocoder 1.1.9 → 1.8.0
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 +309 -0
- data/LICENSE +1 -1
- data/README.md +544 -540
- data/bin/console +13 -0
- data/examples/app_defined_lookup_services.rb +22 -0
- data/examples/reverse_geocode_job.rb +40 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +22 -16
- data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
- data/lib/generators/geocoder/migration_version.rb +15 -0
- data/lib/geocoder/cache.rb +20 -32
- data/lib/geocoder/cache_stores/base.rb +40 -0
- data/lib/geocoder/cache_stores/generic.rb +35 -0
- data/lib/geocoder/cache_stores/redis.rb +34 -0
- data/lib/geocoder/calculations.rb +67 -36
- data/lib/geocoder/cli.rb +2 -2
- data/lib/geocoder/configuration.rb +33 -16
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +19 -0
- data/lib/geocoder/ip_address.rb +33 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +74 -11
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amap.rb +63 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
- data/lib/geocoder/lookups/baidu.rb +24 -15
- data/lib/geocoder/lookups/baidu_ip.rb +30 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +143 -0
- data/lib/geocoder/lookups/base.rb +109 -23
- data/lib/geocoder/lookups/bing.rb +45 -10
- data/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/lib/geocoder/lookups/dstk.rb +4 -2
- data/lib/geocoder/lookups/esri.rb +61 -8
- data/lib/geocoder/lookups/freegeoip.rb +25 -6
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +5 -6
- data/lib/geocoder/lookups/geocodio.rb +42 -0
- data/lib/geocoder/lookups/geoip2.rb +49 -0
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +45 -12
- data/lib/geocoder/lookups/google_places_details.rb +64 -0
- data/lib/geocoder/lookups/google_places_search.rb +76 -0
- data/lib/geocoder/lookups/google_premier.rb +16 -2
- data/lib/geocoder/lookups/here.rb +73 -0
- data/lib/geocoder/lookups/ip2location.rb +71 -0
- data/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/ipstack.rb +63 -0
- data/lib/geocoder/lookups/latlon.rb +58 -0
- data/lib/geocoder/lookups/location_iq.rb +54 -0
- data/lib/geocoder/lookups/mapbox.rb +59 -0
- data/lib/geocoder/lookups/mapquest.rb +9 -10
- data/lib/geocoder/lookups/maxmind.rb +10 -8
- data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/lib/geocoder/lookups/maxmind_local.rb +71 -0
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/nominatim.rb +26 -6
- data/lib/geocoder/lookups/opencagedata.rb +65 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pelias.rb +63 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/pickpoint.rb +41 -0
- data/lib/geocoder/lookups/pointpin.rb +69 -0
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
- data/lib/geocoder/lookups/postcodes_io.rb +31 -0
- data/lib/geocoder/lookups/smarty_streets.rb +68 -0
- data/lib/geocoder/lookups/telize.rb +75 -0
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/twogis.rb +58 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +18 -11
- data/lib/geocoder/models/active_record.rb +9 -4
- data/lib/geocoder/models/base.rb +1 -4
- data/lib/geocoder/models/mongo_base.rb +6 -4
- data/lib/geocoder/query.rb +23 -5
- data/lib/geocoder/railtie.rb +2 -2
- data/lib/geocoder/request.rb +102 -11
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amap.rb +87 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/baidu.rb +10 -14
- data/lib/geocoder/results/baidu_ip.rb +62 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +282 -0
- data/lib/geocoder/results/base.rb +13 -1
- data/lib/geocoder/results/bing.rb +5 -1
- data/lib/geocoder/results/db_ip_com.rb +58 -0
- data/lib/geocoder/results/esri.rb +35 -8
- data/lib/geocoder/results/freegeoip.rb +2 -7
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/geocoder_ca.rb +3 -3
- data/lib/geocoder/results/geocodio.rb +78 -0
- data/lib/geocoder/results/geoip2.rb +76 -0
- data/lib/geocoder/results/geoportail_lu.rb +71 -0
- data/lib/geocoder/results/google.rb +26 -0
- data/lib/geocoder/results/google_places_details.rb +39 -0
- data/lib/geocoder/results/google_places_search.rb +52 -0
- data/lib/geocoder/results/here.rb +77 -0
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipapi_com.rb +45 -0
- data/lib/geocoder/results/ipdata_co.rb +40 -0
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/ipstack.rb +60 -0
- data/lib/geocoder/results/latlon.rb +71 -0
- data/lib/geocoder/results/location_iq.rb +6 -0
- data/lib/geocoder/results/mapbox.rb +63 -0
- data/lib/geocoder/results/mapquest.rb +5 -8
- data/lib/geocoder/results/maxmind.rb +0 -5
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +44 -0
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +41 -14
- data/lib/geocoder/results/opencagedata.rb +100 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/results/pickpoint.rb +6 -0
- data/lib/geocoder/results/pointpin.rb +40 -0
- data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
- data/lib/geocoder/results/postcodes_io.rb +40 -0
- data/lib/geocoder/results/smarty_streets.rb +142 -0
- data/lib/geocoder/results/telize.rb +40 -0
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +20 -3
- data/lib/geocoder/results/twogis.rb +76 -0
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +244 -32
- data/lib/geocoder/sql.rb +25 -21
- data/lib/geocoder/stores/active_record.rb +82 -26
- data/lib/geocoder/stores/base.rb +9 -14
- data/lib/geocoder/stores/mongo_base.rb +0 -31
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/geocoder.rb +6 -13
- data/lib/maxmind_database.rb +109 -0
- data/lib/tasks/geocoder.rake +30 -3
- data/lib/tasks/maxmind.rake +73 -0
- metadata +115 -98
- data/.gitignore +0 -5
- data/.travis.yml +0 -27
- data/Rakefile +0 -25
- data/examples/autoexpire_cache_dalli.rb +0 -62
- data/examples/autoexpire_cache_redis.rb +0 -28
- data/gemfiles/Gemfile.mongoid-2.4.x +0 -15
- data/lib/geocoder/lookups/geocoder_us.rb +0 -39
- data/lib/geocoder/lookups/ovi.rb +0 -62
- data/lib/geocoder/lookups/yahoo.rb +0 -86
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/geocoder/results/ovi.rb +0 -62
- data/lib/geocoder/results/yahoo.rb +0 -55
- data/lib/hash_recursive_merge.rb +0 -74
- data/lib/oauth_util.rb +0 -112
- data/test/active_record_test.rb +0 -15
- data/test/cache_test.rb +0 -35
- data/test/calculations_test.rb +0 -211
- data/test/configuration_test.rb +0 -78
- data/test/custom_block_test.rb +0 -32
- data/test/error_handling_test.rb +0 -43
- data/test/fixtures/baidu_invalid_key +0 -1
- data/test/fixtures/baidu_no_results +0 -1
- data/test/fixtures/baidu_reverse +0 -1
- data/test/fixtures/baidu_shanghai_pearl_tower +0 -12
- data/test/fixtures/bing_invalid_key +0 -1
- data/test/fixtures/bing_madison_square_garden +0 -40
- data/test/fixtures/bing_no_results +0 -16
- data/test/fixtures/bing_reverse +0 -42
- data/test/fixtures/esri_madison_square_garden +0 -59
- data/test/fixtures/esri_no_results +0 -8
- data/test/fixtures/esri_reverse +0 -21
- data/test/fixtures/freegeoip_74_200_247_59 +0 -12
- data/test/fixtures/freegeoip_no_results +0 -1
- data/test/fixtures/geocoder_ca_madison_square_garden +0 -1
- data/test/fixtures/geocoder_ca_no_results +0 -1
- data/test/fixtures/geocoder_ca_reverse +0 -34
- data/test/fixtures/geocoder_us_madison_square_garden +0 -1
- data/test/fixtures/geocoder_us_no_results +0 -1
- data/test/fixtures/google_garbage +0 -456
- data/test/fixtures/google_madison_square_garden +0 -57
- data/test/fixtures/google_no_city_data +0 -44
- data/test/fixtures/google_no_locality +0 -51
- data/test/fixtures/google_no_results +0 -4
- data/test/fixtures/google_over_limit +0 -4
- data/test/fixtures/mapquest_error +0 -16
- data/test/fixtures/mapquest_invalid_api_key +0 -16
- data/test/fixtures/mapquest_invalid_request +0 -16
- data/test/fixtures/mapquest_madison_square_garden +0 -52
- data/test/fixtures/mapquest_no_results +0 -16
- data/test/fixtures/maxmind_24_24_24_21 +0 -1
- data/test/fixtures/maxmind_24_24_24_22 +0 -1
- data/test/fixtures/maxmind_24_24_24_23 +0 -1
- data/test/fixtures/maxmind_24_24_24_24 +0 -1
- data/test/fixtures/maxmind_74_200_247_59 +0 -1
- data/test/fixtures/maxmind_invalid_key +0 -1
- data/test/fixtures/maxmind_no_results +0 -1
- data/test/fixtures/nominatim_madison_square_garden +0 -150
- data/test/fixtures/nominatim_no_results +0 -1
- data/test/fixtures/ovi_madison_square_garden +0 -72
- data/test/fixtures/ovi_no_results +0 -8
- data/test/fixtures/yahoo_error +0 -1
- data/test/fixtures/yahoo_invalid_key +0 -2
- data/test/fixtures/yahoo_madison_square_garden +0 -52
- data/test/fixtures/yahoo_no_results +0 -10
- data/test/fixtures/yahoo_over_limit +0 -2
- data/test/fixtures/yandex_invalid_key +0 -1
- data/test/fixtures/yandex_kremlin +0 -48
- data/test/fixtures/yandex_no_city_and_town +0 -112
- data/test/fixtures/yandex_no_results +0 -16
- data/test/geocoder_test.rb +0 -59
- data/test/https_test.rb +0 -16
- data/test/integration/smoke_test.rb +0 -26
- data/test/lookup_test.rb +0 -117
- data/test/method_aliases_test.rb +0 -25
- data/test/mongoid_test.rb +0 -46
- data/test/mongoid_test_helper.rb +0 -43
- data/test/near_test.rb +0 -61
- data/test/oauth_util_test.rb +0 -30
- data/test/proxy_test.rb +0 -36
- data/test/query_test.rb +0 -52
- data/test/request_test.rb +0 -29
- data/test/result_test.rb +0 -42
- data/test/services_test.rb +0 -393
- data/test/test_helper.rb +0 -289
- data/test/test_mode_test.rb +0 -59
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'geocoder/lookups/base'
|
|
4
|
+
require 'geocoder/results/abstract_api'
|
|
5
|
+
|
|
6
|
+
module Geocoder::Lookup
|
|
7
|
+
class AbstractApi < Base
|
|
8
|
+
|
|
9
|
+
def name
|
|
10
|
+
"Abstract API"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def required_api_key_parts
|
|
14
|
+
['api_key']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def supported_protocols
|
|
18
|
+
[:https]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private # ---------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
def base_query_url(query)
|
|
24
|
+
"#{protocol}://ipgeolocation.abstractapi.com/v1/?"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def query_url_params(query)
|
|
28
|
+
params = {api_key: configuration.api_key}
|
|
29
|
+
|
|
30
|
+
ip_address = query.sanitized_text
|
|
31
|
+
if ip_address.is_a?(String) && ip_address.length > 0
|
|
32
|
+
params[:ip_address] = ip_address
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
params.merge(super)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def results(query, reverse = false)
|
|
39
|
+
if doc = fetch_data(query)
|
|
40
|
+
[doc]
|
|
41
|
+
else
|
|
42
|
+
[]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require "geocoder/results/amap"
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class Amap < Base
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"AMap"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def required_api_key_parts
|
|
12
|
+
["key"]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def supported_protocols
|
|
16
|
+
[:http]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ---------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def base_query_url(query)
|
|
22
|
+
path = query.reverse_geocode? ? 'regeo' : 'geo'
|
|
23
|
+
"http://restapi.amap.com/v3/geocode/#{path}?"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def results(query, reverse = false)
|
|
27
|
+
return [] unless doc = fetch_data(query)
|
|
28
|
+
case [doc['status'], doc['info']]
|
|
29
|
+
when ['1', 'OK']
|
|
30
|
+
return doc['regeocodes'] unless doc['regeocodes'].blank?
|
|
31
|
+
return [doc['regeocode']] unless doc['regeocode'].blank?
|
|
32
|
+
return doc['geocodes'] unless doc['geocodes'].blank?
|
|
33
|
+
when ['0', 'INVALID_USER_KEY']
|
|
34
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
|
35
|
+
warn("#{self.name} Geocoding API error: invalid api key.")
|
|
36
|
+
else
|
|
37
|
+
raise_error(Geocoder::Error, "server error.") ||
|
|
38
|
+
warn("#{self.name} Geocoding API error: server error - [#{doc['info']}]")
|
|
39
|
+
end
|
|
40
|
+
return []
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def query_url_params(query)
|
|
44
|
+
params = {
|
|
45
|
+
:key => configuration.api_key,
|
|
46
|
+
:output => "json"
|
|
47
|
+
}
|
|
48
|
+
if query.reverse_geocode?
|
|
49
|
+
params[:location] = revert_coordinates(query.text)
|
|
50
|
+
params[:extensions] = "all"
|
|
51
|
+
params[:coordsys] = "gps"
|
|
52
|
+
else
|
|
53
|
+
params[:address] = query.sanitized_text
|
|
54
|
+
end
|
|
55
|
+
params.merge(super)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def revert_coordinates(text)
|
|
59
|
+
[text[1],text[0]].join(",")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'geocoder/lookups/base'
|
|
2
|
+
require 'geocoder/results/amazon_location_service'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class AmazonLocationService < Base
|
|
6
|
+
def results(query)
|
|
7
|
+
params = query.options.dup
|
|
8
|
+
|
|
9
|
+
# index_name is required
|
|
10
|
+
# Aws::ParamValidator raises ArgumentError on missing required keys
|
|
11
|
+
params.merge!(index_name: configuration[:index_name])
|
|
12
|
+
|
|
13
|
+
# Aws::ParamValidator raises ArgumentError on unexpected keys
|
|
14
|
+
params.delete(:lookup)
|
|
15
|
+
|
|
16
|
+
resp = if query.reverse_geocode?
|
|
17
|
+
client.search_place_index_for_position(params.merge(position: query.coordinates.reverse))
|
|
18
|
+
else
|
|
19
|
+
client.search_place_index_for_text(params.merge(text: query.text))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
resp.results.map(&:place)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def client
|
|
28
|
+
return @client if @client
|
|
29
|
+
require_sdk
|
|
30
|
+
keys = configuration.api_key
|
|
31
|
+
if keys
|
|
32
|
+
@client = Aws::LocationService::Client.new(
|
|
33
|
+
access_key_id: keys[:access_key_id],
|
|
34
|
+
secret_access_key: keys[:secret_access_key],
|
|
35
|
+
)
|
|
36
|
+
else
|
|
37
|
+
@client = Aws::LocationService::Client.new
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def require_sdk
|
|
42
|
+
begin
|
|
43
|
+
require 'aws-sdk-locationservice'
|
|
44
|
+
rescue LoadError
|
|
45
|
+
raise_error(Geocoder::ConfigurationError) ||
|
|
46
|
+
Geocoder.log(
|
|
47
|
+
:error,
|
|
48
|
+
"Couldn't load the Amazon Location Service SDK. " +
|
|
49
|
+
"Install it with: gem install aws-sdk-locationservice -v '~> 1.4'"
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -12,31 +12,41 @@ module Geocoder::Lookup
|
|
|
12
12
|
["key"]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
# HTTP only
|
|
16
|
+
def supported_protocols
|
|
17
|
+
[:http]
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
private # ---------------------------------------------------------------
|
|
20
21
|
|
|
22
|
+
def base_query_url(query)
|
|
23
|
+
"#{protocol}://api.map.baidu.com/geocoder/v2/?"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def content_key
|
|
27
|
+
'result'
|
|
28
|
+
end
|
|
29
|
+
|
|
21
30
|
def results(query, reverse = false)
|
|
22
31
|
return [] unless doc = fetch_data(query)
|
|
23
|
-
case doc['status']
|
|
24
|
-
|
|
32
|
+
case doc['status']
|
|
33
|
+
when 0
|
|
34
|
+
return [doc[content_key]] unless doc[content_key].blank?
|
|
25
35
|
when 1, 3, 4
|
|
26
|
-
raise_error(Geocoder::Error,
|
|
27
|
-
warn
|
|
36
|
+
raise_error(Geocoder::Error, "server error.") ||
|
|
37
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: server error.")
|
|
28
38
|
when 2
|
|
29
|
-
raise_error(Geocoder::InvalidRequest,
|
|
30
|
-
warn
|
|
39
|
+
raise_error(Geocoder::InvalidRequest, "invalid request.") ||
|
|
40
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: invalid request.")
|
|
31
41
|
when 5
|
|
32
|
-
raise_error(Geocoder::InvalidApiKey,
|
|
33
|
-
warn
|
|
42
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
|
43
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
|
|
34
44
|
when 101, 102, 200..299
|
|
35
|
-
raise_error(Geocoder::RequestDenied) ||
|
|
36
|
-
warn
|
|
45
|
+
raise_error(Geocoder::RequestDenied, "request denied") ||
|
|
46
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: request denied.")
|
|
37
47
|
when 300..399
|
|
38
|
-
raise_error(Geocoder::OverQueryLimitError) ||
|
|
39
|
-
warn
|
|
48
|
+
raise_error(Geocoder::OverQueryLimitError, "over query limit.") ||
|
|
49
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: over query limit.")
|
|
40
50
|
end
|
|
41
51
|
return []
|
|
42
52
|
end
|
|
@@ -51,4 +61,3 @@ module Geocoder::Lookup
|
|
|
51
61
|
|
|
52
62
|
end
|
|
53
63
|
end
|
|
54
|
-
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'geocoder/lookups/baidu'
|
|
2
|
+
require 'geocoder/results/baidu_ip'
|
|
3
|
+
|
|
4
|
+
module Geocoder::Lookup
|
|
5
|
+
class BaiduIp < Baidu
|
|
6
|
+
|
|
7
|
+
def name
|
|
8
|
+
"Baidu IP"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private # ---------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
def base_query_url(query)
|
|
14
|
+
"#{protocol}://api.map.baidu.com/location/ip?"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def content_key
|
|
18
|
+
'content'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def query_url_params(query)
|
|
22
|
+
{
|
|
23
|
+
:ip => query.sanitized_text,
|
|
24
|
+
:ak => configuration.api_key,
|
|
25
|
+
:coor => "bd09ll"
|
|
26
|
+
}.merge(super)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'geocoder/lookups/base'
|
|
4
|
+
require 'geocoder/results/ban_data_gouv_fr'
|
|
5
|
+
|
|
6
|
+
module Geocoder::Lookup
|
|
7
|
+
class BanDataGouvFr < Base
|
|
8
|
+
|
|
9
|
+
def name
|
|
10
|
+
"Base Adresse Nationale Française"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def map_link_url(coordinates)
|
|
14
|
+
"https://www.openstreetmap.org/#map=19/#{coordinates.join('/')}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private # ---------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
def base_query_url(query)
|
|
20
|
+
method = query.reverse_geocode? ? "reverse" : "search"
|
|
21
|
+
"#{protocol}://api-adresse.data.gouv.fr/#{method}/?"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def any_result?(doc)
|
|
25
|
+
doc['features'] and doc['features'].any?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def results(query)
|
|
29
|
+
if doc = fetch_data(query) and any_result?(doc)
|
|
30
|
+
[doc]
|
|
31
|
+
else
|
|
32
|
+
[]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#### PARAMS ####
|
|
37
|
+
|
|
38
|
+
def query_url_params(query)
|
|
39
|
+
query_ban_datagouv_fr_params(query).merge(super)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def query_ban_datagouv_fr_params(query)
|
|
43
|
+
query.reverse_geocode? ? reverse_geocode_ban_fr_params(query) : search_geocode_ban_fr_params(query)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#### SEARCH GEOCODING PARAMS ####
|
|
47
|
+
#
|
|
48
|
+
# :q => required, full text search param)
|
|
49
|
+
|
|
50
|
+
# :limit => force limit number of results returned by raw API
|
|
51
|
+
# (default = 5) note : only first result is taken
|
|
52
|
+
# in account in geocoder
|
|
53
|
+
#
|
|
54
|
+
# :autocomplete => pass 0 to disable autocomplete treatment of :q
|
|
55
|
+
# (default = 1)
|
|
56
|
+
#
|
|
57
|
+
# :lat => force filter results around specific lat/lon
|
|
58
|
+
#
|
|
59
|
+
# :lon => force filter results around specific lat/lon
|
|
60
|
+
#
|
|
61
|
+
# :type => force filter the returned result type
|
|
62
|
+
# (check results for a list of accepted types)
|
|
63
|
+
#
|
|
64
|
+
# :postcode => force filter results on a specific city post code
|
|
65
|
+
#
|
|
66
|
+
# :citycode => force filter results on a specific city UUID INSEE code
|
|
67
|
+
#
|
|
68
|
+
# For up to date doc (in french only) : https://adresse.data.gouv.fr/api/
|
|
69
|
+
#
|
|
70
|
+
def search_geocode_ban_fr_params(query)
|
|
71
|
+
params = {
|
|
72
|
+
q: query.sanitized_text
|
|
73
|
+
}
|
|
74
|
+
unless (limit = query.options[:limit]).nil? || !limit_param_is_valid?(limit)
|
|
75
|
+
params[:limit] = limit.to_i
|
|
76
|
+
end
|
|
77
|
+
unless (autocomplete = query.options[:autocomplete]).nil? || !autocomplete_param_is_valid?(autocomplete)
|
|
78
|
+
params[:autocomplete] = autocomplete.to_s
|
|
79
|
+
end
|
|
80
|
+
unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
|
|
81
|
+
params[:type] = type.downcase
|
|
82
|
+
end
|
|
83
|
+
unless (postcode = query.options[:postcode]).nil? || !code_param_is_valid?(postcode)
|
|
84
|
+
params[:postcode] = postcode.to_s
|
|
85
|
+
end
|
|
86
|
+
unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
|
|
87
|
+
params[:citycode] = citycode.to_s
|
|
88
|
+
end
|
|
89
|
+
unless (lat = query.options[:lat]).nil? || !latitude_is_valid?(lat)
|
|
90
|
+
params[:lat] = lat
|
|
91
|
+
end
|
|
92
|
+
unless (lon = query.options[:lon]).nil? || !longitude_is_valid?(lon)
|
|
93
|
+
params[:lon] = lon
|
|
94
|
+
end
|
|
95
|
+
params
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
#### REVERSE GEOCODING PARAMS ####
|
|
99
|
+
#
|
|
100
|
+
# :lat => required
|
|
101
|
+
#
|
|
102
|
+
# :lon => required
|
|
103
|
+
#
|
|
104
|
+
# :type => force returned results type
|
|
105
|
+
# (check results for a list of accepted types)
|
|
106
|
+
#
|
|
107
|
+
def reverse_geocode_ban_fr_params(query)
|
|
108
|
+
lat_lon = query.coordinates
|
|
109
|
+
params = {
|
|
110
|
+
lat: lat_lon.first,
|
|
111
|
+
lon: lat_lon.last
|
|
112
|
+
}
|
|
113
|
+
unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
|
|
114
|
+
params[:type] = type.downcase
|
|
115
|
+
end
|
|
116
|
+
params
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def limit_param_is_valid?(param)
|
|
120
|
+
param.to_i.positive?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def autocomplete_param_is_valid?(param)
|
|
124
|
+
[0,1].include?(param.to_i)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def type_param_is_valid?(param)
|
|
128
|
+
%w(housenumber street locality village town city).include?(param.downcase)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def code_param_is_valid?(param)
|
|
132
|
+
(1..99999).include?(param.to_i)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def latitude_is_valid?(param)
|
|
136
|
+
param.to_f <= 90 && param.to_f >= -90
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def longitude_is_valid?(param)
|
|
140
|
+
param.to_f <= 180 && param.to_f >= -180
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -4,7 +4,6 @@ require 'uri'
|
|
|
4
4
|
|
|
5
5
|
unless defined?(ActiveSupport::JSON)
|
|
6
6
|
begin
|
|
7
|
-
require 'rubygems' # for Ruby 1.8
|
|
8
7
|
require 'json'
|
|
9
8
|
rescue LoadError
|
|
10
9
|
raise LoadError, "Please install the 'json' or 'json_pure' gem to parse geocoder results."
|
|
@@ -15,6 +14,9 @@ module Geocoder
|
|
|
15
14
|
module Lookup
|
|
16
15
|
|
|
17
16
|
class Base
|
|
17
|
+
def initialize
|
|
18
|
+
@cache = nil
|
|
19
|
+
end
|
|
18
20
|
|
|
19
21
|
##
|
|
20
22
|
# Human-readable name of the geocoding API.
|
|
@@ -69,8 +71,12 @@ module Geocoder
|
|
|
69
71
|
##
|
|
70
72
|
# URL to use for querying the geocoding engine.
|
|
71
73
|
#
|
|
74
|
+
# Subclasses should not modify this method. Instead they should define
|
|
75
|
+
# base_query_url and url_query_string. If absolutely necessary to
|
|
76
|
+
# subclss this method, they must also subclass #cache_key.
|
|
77
|
+
#
|
|
72
78
|
def query_url(query)
|
|
73
|
-
|
|
79
|
+
base_query_url(query) + url_query_string(query)
|
|
74
80
|
end
|
|
75
81
|
|
|
76
82
|
##
|
|
@@ -78,13 +84,31 @@ module Geocoder
|
|
|
78
84
|
#
|
|
79
85
|
def cache
|
|
80
86
|
if @cache.nil? and store = configuration.cache
|
|
81
|
-
|
|
87
|
+
cache_options = configuration.cache_options
|
|
88
|
+
@cache = Cache.new(store, cache_options)
|
|
82
89
|
end
|
|
83
90
|
@cache
|
|
84
91
|
end
|
|
85
92
|
|
|
93
|
+
##
|
|
94
|
+
# Array containing the protocols supported by the api.
|
|
95
|
+
# Should be set to [:http] if only HTTP is supported
|
|
96
|
+
# or [:https] if only HTTPS is supported.
|
|
97
|
+
#
|
|
98
|
+
def supported_protocols
|
|
99
|
+
[:http, :https]
|
|
100
|
+
end
|
|
101
|
+
|
|
86
102
|
private # -------------------------------------------------------------
|
|
87
103
|
|
|
104
|
+
##
|
|
105
|
+
# String which, when concatenated with url_query_string(query)
|
|
106
|
+
# produces the full query URL. Should include the "?" a the end.
|
|
107
|
+
#
|
|
108
|
+
def base_query_url(query)
|
|
109
|
+
fail
|
|
110
|
+
end
|
|
111
|
+
|
|
88
112
|
##
|
|
89
113
|
# An object with configuration data for this particular lookup.
|
|
90
114
|
#
|
|
@@ -96,7 +120,6 @@ module Geocoder
|
|
|
96
120
|
# Object used to make HTTP requests.
|
|
97
121
|
#
|
|
98
122
|
def http_client
|
|
99
|
-
protocol = "http#{'s' if configuration.use_https}"
|
|
100
123
|
proxy_name = "#{protocol}_proxy"
|
|
101
124
|
if proxy = configuration.send(proxy_name)
|
|
102
125
|
proxy_url = !!(proxy =~ /^#{protocol}/) ? proxy : protocol + '://' + proxy
|
|
@@ -136,7 +159,14 @@ module Geocoder
|
|
|
136
159
|
# something else (like the URL before OAuth encoding).
|
|
137
160
|
#
|
|
138
161
|
def cache_key(query)
|
|
139
|
-
|
|
162
|
+
base_query_url(query) + hash_to_query(cache_key_params(query))
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def cache_key_params(query)
|
|
166
|
+
# omit api_key and token because they may vary among requests
|
|
167
|
+
query_url_params(query).reject do |key,value|
|
|
168
|
+
key.to_s.match(/(key|token)/)
|
|
169
|
+
end
|
|
140
170
|
end
|
|
141
171
|
|
|
142
172
|
##
|
|
@@ -165,10 +195,14 @@ module Geocoder
|
|
|
165
195
|
def fetch_data(query)
|
|
166
196
|
parse_raw_data fetch_raw_data(query)
|
|
167
197
|
rescue SocketError => err
|
|
168
|
-
raise_error(err) or warn "Geocoding API connection cannot be established."
|
|
169
|
-
rescue
|
|
170
|
-
raise_error(err) or warn "Geocoding API
|
|
171
|
-
|
|
198
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
|
|
199
|
+
rescue Errno::ECONNREFUSED => err
|
|
200
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
|
|
201
|
+
rescue Geocoder::NetworkError => err
|
|
202
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
|
|
203
|
+
rescue Timeout::Error => err
|
|
204
|
+
raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
|
|
205
|
+
"(use Geocoder.configure(:timeout => ...) to set limit).")
|
|
172
206
|
end
|
|
173
207
|
|
|
174
208
|
def parse_json(data)
|
|
@@ -177,6 +211,11 @@ module Geocoder
|
|
|
177
211
|
else
|
|
178
212
|
JSON.parse(data)
|
|
179
213
|
end
|
|
214
|
+
rescue
|
|
215
|
+
unless raise_error(ResponseParseError.new(data))
|
|
216
|
+
Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
|
|
217
|
+
Geocoder.log(:debug, "Raw response: #{data}")
|
|
218
|
+
end
|
|
180
219
|
end
|
|
181
220
|
|
|
182
221
|
##
|
|
@@ -184,8 +223,6 @@ module Geocoder
|
|
|
184
223
|
#
|
|
185
224
|
def parse_raw_data(raw_data)
|
|
186
225
|
parse_json(raw_data)
|
|
187
|
-
rescue
|
|
188
|
-
warn "Geocoding API's response was not valid JSON."
|
|
189
226
|
end
|
|
190
227
|
|
|
191
228
|
##
|
|
@@ -193,7 +230,7 @@ module Geocoder
|
|
|
193
230
|
# Set in configuration but not available for every service.
|
|
194
231
|
#
|
|
195
232
|
def protocol
|
|
196
|
-
"http" + (
|
|
233
|
+
"http" + (use_ssl? ? "s" : "")
|
|
197
234
|
end
|
|
198
235
|
|
|
199
236
|
def valid_response?(response)
|
|
@@ -211,7 +248,21 @@ module Geocoder
|
|
|
211
248
|
else
|
|
212
249
|
check_api_key_configuration!(query)
|
|
213
250
|
response = make_api_request(query)
|
|
251
|
+
check_response_for_errors!(response)
|
|
214
252
|
body = response.body
|
|
253
|
+
|
|
254
|
+
# apply the charset from the Content-Type header, if possible
|
|
255
|
+
ct = response['content-type']
|
|
256
|
+
|
|
257
|
+
if ct && ct['charset']
|
|
258
|
+
charset = ct.split(';').select do |s|
|
|
259
|
+
s['charset']
|
|
260
|
+
end.first.to_s.split('=')
|
|
261
|
+
if charset.length == 2
|
|
262
|
+
body.force_encoding(charset.last) rescue ArgumentError
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
215
266
|
if cache and valid_response?(response)
|
|
216
267
|
cache[key] = body
|
|
217
268
|
end
|
|
@@ -220,26 +271,61 @@ module Geocoder
|
|
|
220
271
|
body
|
|
221
272
|
end
|
|
222
273
|
|
|
274
|
+
def check_response_for_errors!(response)
|
|
275
|
+
if response.code.to_i == 400
|
|
276
|
+
raise_error(Geocoder::InvalidRequest) ||
|
|
277
|
+
Geocoder.log(:warn, "Geocoding API error: 400 Bad Request")
|
|
278
|
+
elsif response.code.to_i == 401
|
|
279
|
+
raise_error(Geocoder::RequestDenied) ||
|
|
280
|
+
Geocoder.log(:warn, "Geocoding API error: 401 Unauthorized")
|
|
281
|
+
elsif response.code.to_i == 402
|
|
282
|
+
raise_error(Geocoder::OverQueryLimitError) ||
|
|
283
|
+
Geocoder.log(:warn, "Geocoding API error: 402 Payment Required")
|
|
284
|
+
elsif response.code.to_i == 429
|
|
285
|
+
raise_error(Geocoder::OverQueryLimitError) ||
|
|
286
|
+
Geocoder.log(:warn, "Geocoding API error: 429 Too Many Requests")
|
|
287
|
+
elsif response.code.to_i == 503
|
|
288
|
+
raise_error(Geocoder::ServiceUnavailable) ||
|
|
289
|
+
Geocoder.log(:warn, "Geocoding API error: 503 Service Unavailable")
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
223
293
|
##
|
|
224
294
|
# Make an HTTP(S) request to a geocoding API and
|
|
225
295
|
# return the response object.
|
|
226
296
|
#
|
|
227
297
|
def make_api_request(query)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
client.request(req)
|
|
298
|
+
uri = URI.parse(query_url(query))
|
|
299
|
+
Geocoder.log(:debug, "Geocoder: HTTP request being made for #{uri.to_s}")
|
|
300
|
+
http_client.start(uri.host, uri.port, use_ssl: use_ssl?, open_timeout: configuration.timeout, read_timeout: configuration.timeout) do |client|
|
|
301
|
+
configure_ssl!(client) if use_ssl?
|
|
302
|
+
req = Net::HTTP::Get.new(uri.request_uri, configuration.http_headers)
|
|
303
|
+
if configuration.basic_auth[:user] and configuration.basic_auth[:password]
|
|
304
|
+
req.basic_auth(
|
|
305
|
+
configuration.basic_auth[:user],
|
|
306
|
+
configuration.basic_auth[:password]
|
|
307
|
+
)
|
|
239
308
|
end
|
|
309
|
+
client.request(req)
|
|
240
310
|
end
|
|
311
|
+
rescue Timeout::Error
|
|
312
|
+
raise Geocoder::LookupTimeout
|
|
313
|
+
rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
|
|
314
|
+
raise Geocoder::NetworkError
|
|
241
315
|
end
|
|
242
316
|
|
|
317
|
+
def use_ssl?
|
|
318
|
+
if supported_protocols == [:https]
|
|
319
|
+
true
|
|
320
|
+
elsif supported_protocols == [:http]
|
|
321
|
+
false
|
|
322
|
+
else
|
|
323
|
+
configuration.use_https
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def configure_ssl!(client); end
|
|
328
|
+
|
|
243
329
|
def check_api_key_configuration!(query)
|
|
244
330
|
key_parts = query.lookup.required_api_key_parts
|
|
245
331
|
if key_parts.size > Array(configuration.api_key).size
|