diff --git a/Gemfile b/Gemfile index e64517f55..2ff6837f8 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ group :development, :test do gem 'rubyzip' gem 'rails', '~>5.1.0' gem 'test-unit' # needed for Ruby >=2.2.0 + gem 'ip2location_ruby' platforms :jruby do gem 'jruby-openssl' diff --git a/README_API_GUIDE.md b/README_API_GUIDE.md index 0b064d911..704ccf110 100644 --- a/README_API_GUIDE.md +++ b/README_API_GUIDE.md @@ -52,6 +52,7 @@ Global Street Address Lookups amazon_location_service: { index_name: 'YOUR_INDEX_NAME_GOES_HERE', api_key: { + region: 'YOUR_INDEX_REGION', access_key_id: 'YOUR_AWS_ACCESS_KEY_ID_GOES_HERE', secret_access_key: 'YOUR_AWS_SECRET_ACCESS_KEY_GOES_HERE', } @@ -499,6 +500,16 @@ Regional Street Address Lookups * **Documentation**: http://geodata.nationaalgeoregister.nl/ * **Terms of Service**: https://www.pdok.nl/over-pdok - The PDOK services are based on open data and are therefore freely available to everyone. +### pdok NL (`:pdok_nl`) + +* **API key**: none +* **Quota**: none +* **Region**: Netherlands +* **SSL support**: yes, required +* **Languages**: Dutch +* **Documentation**: https://api.pdok.nl/bzk/locatieserver/search/v3_1/ui/#/Locatieserver/free +* **Terms of Service**: https://www.pdok.nl/over-pdok - The PDOK services are based on open data and are therefore freely available to everyone. + ### Ordnance Survey OpenNames (`:uk_ordnance_survey_names`) * **API key**: required (sign up at https://developer.ordnancesurvey.co.uk/os-names-api) @@ -749,6 +760,16 @@ IP Address Lookups * **Terms of Service**: * **Limitations**: +### IP2Location.io (`:ip2location_io`) + +* **API key**: required (30,000 free queries given on FREE plan) +* **Quota**: up to 600k queries with paid API key +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: https://www.ip2location.io/ip2location-documentation +* **Terms of Service**: https://www.ip2location.io/terms-of-service + Local IP Address Lookups ------------------------ @@ -817,4 +838,26 @@ You can generate ActiveRecord migrations and download and import data via provid You can replace `city` with `country` in any of the above tasks, generators, and configurations. +### IP2Location LITE (`:ip2location_lite`) + +This lookup provides methods for geocoding IP addresses without making a call to a remote API (improves speed and availability). + +* **API key**: none (requires a IP2Location or FREE IP2Location LITE binary database which can be downloaded from [IP2Location LITE](https://lite.ip2location.com/)) +* **Quota**: none +* **Region**: world +* **SSL support**: N/A +* **Languages**: English +* **Documentation**: https://lite.ip2location.com/ +* **Terms of Service**: https://lite.ip2location.com/ +* **Notes**: **You must download a binary database (BIN) file from IP2Location LITE and set the `:file` configuration option.** Set the path to the database file in your configuration: + + Geocoder.configure( + ip_lookup: :ip2location_lite, + ip2location_lite: { + file: File.join('folder', 'IP2LOCATION-LITE-DB11.BIN') + } + ) + +You must add the *[ip2location_ruby](https://rubygems.org/gems/ip2location_ruby)* gem (pure Ruby implementation) to your Gemfile or have it installed in your system. + Copyright (c) 2009-2021 Alex Reisner, released under the MIT license. diff --git a/geocoder.gemspec b/geocoder.gemspec index ed6955a26..505dea33f 100644 --- a/geocoder.gemspec +++ b/geocoder.gemspec @@ -22,4 +22,6 @@ Gem::Specification.new do |s| 'source_code_uri' => 'https://github.com/alexreisner/geocoder', 'changelog_uri' => 'https://github.com/alexreisner/geocoder/blob/master/CHANGELOG.md' } + s.add_dependency("base64", ">= 0.1.0") # for :google_premier lookup + s.add_dependency("csv", ">= 3.0.0") # for :maxmind lookup end diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index 6a1b6d64a..d6bbf0de2 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -23,7 +23,7 @@ def all_services_except_test # For example, Amazon Location Service uses the AWS gem, not HTTP REST requests, to fetch data. # def all_services_with_http_requests - all_services_except_test - [:amazon_location_service] + all_services_except_test - [:amazon_location_service, :maxmind_local, :geoip2, :ip2location_lite] end ## @@ -48,6 +48,7 @@ def street_services :uk_ordnance_survey_names, :opencagedata, :pelias, + :pdok_nl, :pickpoint, :here, :baidu, @@ -95,7 +96,9 @@ def ip_services :ip2location, :ipgeolocation, :ipqualityscore, - :ipbase + :ipbase, + :ip2location_io, + :ip2location_lite ] end diff --git a/lib/geocoder/lookups/google_places_search.rb b/lib/geocoder/lookups/google_places_search.rb index 8b4e0ee2b..ecb9d38a4 100644 --- a/lib/geocoder/lookups/google_places_search.rb +++ b/lib/geocoder/lookups/google_places_search.rb @@ -49,12 +49,11 @@ def fields(query) end def default_fields - legacy = %w[id reference] basic = %w[business_status formatted_address geometry icon name photos place_id plus_code types] contact = %w[opening_hours] atmosphere = %W[price_level rating user_ratings_total] - format_fields(legacy, basic, contact, atmosphere) + format_fields(basic, contact, atmosphere) end def format_fields(*fields) diff --git a/lib/geocoder/lookups/ip2location_io.rb b/lib/geocoder/lookups/ip2location_io.rb new file mode 100644 index 000000000..3a4c2a5ea --- /dev/null +++ b/lib/geocoder/lookups/ip2location_io.rb @@ -0,0 +1,62 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ip2location_io' + +module Geocoder::Lookup + class Ip2locationIo < Base + + def name + "IP2LocationIOApi" + end + + def required_api_key_parts + ['key'] + end + + def supported_protocols + [:http, :https] + end + + private # ---------------------------------------------------------------- + + def base_query_url(query) + "#{protocol}://api.ip2location.io/?" + end + + def query_url_params(query) + super.merge( + key: configuration.api_key, + ip: query.sanitized_text, + ) + end + + def results(query) + # don't look up a loopback or private address, just return the stored result + return [reserved_result(query.text)] if query.internal_ip_address? + return [] unless doc = fetch_data(query) + if doc["response"] == "INVALID ACCOUNT" + raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT") + return [] + else + return [doc] + end + end + + def reserved_result(query) + { + "ip" => "-", + "country_code" => "-", + "country_name" => "-", + "region_name" => "-", + "city_name" => "-", + "latitude" => null, + "longitude" => null, + "zip_code" => "-", + "time_zone" => "-", + "asn" => "-", + "as" => "-", + "is_proxy" => false + } + end + + end +end diff --git a/lib/geocoder/lookups/ip2location_lite.rb b/lib/geocoder/lookups/ip2location_lite.rb new file mode 100644 index 000000000..396ff0af0 --- /dev/null +++ b/lib/geocoder/lookups/ip2location_lite.rb @@ -0,0 +1,40 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ip2location_lite' + +module Geocoder + module Lookup + class Ip2locationLite < Base + attr_reader :gem_name + + def initialize + unless configuration[:file].nil? + begin + @gem_name = 'ip2location_ruby' + require @gem_name + rescue LoadError + raise "Could not load IP2Location DB dependency. To use the IP2LocationLite lookup you must add the #{@gem_name} gem to your Gemfile or have it installed in your system." + end + end + super + end + + def name + 'IP2LocationLite' + end + + def required_api_key_parts + [] + end + + private + + def results(query) + return [] unless configuration[:file] + + i2l = Ip2location.new.open(configuration[:file].to_s) + result = i2l.get_all(query.to_s) + result.nil? ? [] : [result] + end + end + end +end \ No newline at end of file diff --git a/lib/geocoder/lookups/pdok_nl.rb b/lib/geocoder/lookups/pdok_nl.rb new file mode 100644 index 000000000..180d1ed19 --- /dev/null +++ b/lib/geocoder/lookups/pdok_nl.rb @@ -0,0 +1,43 @@ +require 'geocoder/lookups/base' +require "geocoder/results/pdok_nl" + +module Geocoder::Lookup + class PdokNl < Base + + def name + 'pdok NL' + end + + def supported_protocols + [:https] + end + + private # --------------------------------------------------------------- + + def cache_key(query) + base_query_url(query) + hash_to_query(query_url_params(query)) + end + + def base_query_url(query) + "#{protocol}://api.pdok.nl/bzk/locatieserver/search/v3_1/free?" + end + + def valid_response?(response) + json = parse_json(response.body) + super(response) if json + end + + def results(query) + return [] unless doc = fetch_data(query) + return doc['response']['docs'] + end + + def query_url_params(query) + { + fl: '*', + q: query.text, + wt: 'json' + }.merge(super) + end + end +end diff --git a/lib/geocoder/results/ip2location_io.rb b/lib/geocoder/results/ip2location_io.rb new file mode 100644 index 000000000..7df9a0439 --- /dev/null +++ b/lib/geocoder/results/ip2location_io.rb @@ -0,0 +1,21 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Ip2locationIo < Base + + def address(format = :full) + "#{city_name} #{zip_code}, #{country_name}".sub(/^[ ,]*/, '') + end + + def self.response_attributes + %w[ip country_code country_name region_name city_name latitude longitude + zip_code time_zone asn as is_proxy] + end + + response_attributes.each do |attr| + define_method attr do + @data[attr] || "" + end + end + end +end diff --git a/lib/geocoder/results/ip2location_lite.rb b/lib/geocoder/results/ip2location_lite.rb new file mode 100644 index 000000000..82d8b0376 --- /dev/null +++ b/lib/geocoder/results/ip2location_lite.rb @@ -0,0 +1,47 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Ip2locationLite < Base + + def coordinates + [@data[:latitude], @data[:longitude]] + end + + def city + @data[:city] + end + + def state + @data[:region] + end + + def state_code + "" # Not available in Maxmind's database + end + + def country + @data[:country_long] + end + + def country_code + @data[:country_short] + end + + def postal_code + @data[:zipcode] + end + + def self.response_attributes + %w[country_short country_long region latitude longitude isp + domain netspeed areacode iddcode timezone zipcode weatherstationname + weatherstationcode mcc mnc mobilebrand elevation usagetype addresstype + category district asn as] + end + + response_attributes.each do |a| + define_method a do + @data[a] || "" + end + end + end +end \ No newline at end of file diff --git a/lib/geocoder/results/pdok_nl.rb b/lib/geocoder/results/pdok_nl.rb new file mode 100644 index 000000000..8b90dc609 --- /dev/null +++ b/lib/geocoder/results/pdok_nl.rb @@ -0,0 +1,62 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class PdokNl < Base + + def response_attributes + @data + end + + def coordinates + @data['centroide_ll'][6..-2].split(' ').map(&:to_f).reverse + end + + def formatted_address + @data['weergavenaam'] + end + + alias_method :address, :formatted_address + + def province + @data['provincienaam'] + end + + alias_method :state, :province + + def city + @data['woonplaatsnaam'] + end + + def district + @data['gemeentenaam'] + end + + def street + @data['straatnaam'] + end + + def street_number + @data['huis_nlt'] + end + + def address_components + @data + end + + def state_code + @data['provinciecode'] + end + + def postal_code + @data['postcode'] + end + + def country + "Netherlands" + end + + def country_code + "NL" + end + end +end diff --git a/test/fixtures/ip2location_io_8_8_8_8 b/test/fixtures/ip2location_io_8_8_8_8 new file mode 100644 index 000000000..fbd46ee83 --- /dev/null +++ b/test/fixtures/ip2location_io_8_8_8_8 @@ -0,0 +1,14 @@ +{ + "ip":"8.8.8.8", + "country_code":"US", + "country_name":"United States of America", + "region_name":"California", + "city_name":"Mountain View", + "latitude":37.405992, + "longitude":-122.078515, + "zip_code":"94043", + "time_zone":"-07:00", + "asn":"15169", + "as":"Google LLC", + "is_proxy":false +} \ No newline at end of file diff --git a/test/fixtures/ip2location_io_invalid_api_key b/test/fixtures/ip2location_io_invalid_api_key new file mode 100644 index 000000000..b10ad0588 --- /dev/null +++ b/test/fixtures/ip2location_io_invalid_api_key @@ -0,0 +1,6 @@ +{ + "error": { + "error_code": 10000, + "error_message": "Invalid API key or insufficient query." + } +} \ No newline at end of file diff --git a/test/fixtures/ip2location_io_no_results b/test/fixtures/ip2location_io_no_results new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/pdok_nl b/test/fixtures/pdok_nl new file mode 100644 index 000000000..387d2ef96 --- /dev/null +++ b/test/fixtures/pdok_nl @@ -0,0 +1,245 @@ +{ + "response": { + "numFound": 601698, + "start": 0, + "maxScore": 21.486404, + "numFoundExact": true, + "docs": [ + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "adres", + "woonplaatsnaam": "Amsterdam", + "wijkcode": "WK0363AD", + "huis_nlt": "147", + "openbareruimtetype": "Weg", + "buurtnaam": "Nieuwe Kerk e.o.", + "gemeentecode": "0363", + "rdf_seealso": "http://bag.basisregistraties.overheid.nl/bag/id/nummeraanduiding/0363200000218908", + "weergavenaam": "Nieuwezijds Voorburgwal 147, 1012RJ Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "adr-563f90756e46d1c554b4ab00ac61b932", + "gekoppeld_perceel": [ + "ASD04-F-2749" + ], + "gemeentenaam": "Amsterdam", + "buurtcode": "BU0363AD05", + "wijknaam": "Burgwallen-Nieuwe Zijde", + "identificatie": "0363010000758545-0363200000218908", + "openbareruimte_id": "0363300000004690", + "waterschapsnaam": "Hoogheemraadschap Amstel Gooi en Vecht", + "provinciecode": "PV27", + "postcode": "1012RJ", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89089949 52.37316398)", + "nummeraanduiding_id": "0363200000218908", + "waterschapscode": "11", + "adresseerbaarobject_id": "0363010000758545", + "huisnummer": 147, + "provincieafkorting": "NH", + "centroide_rd": "POINT(121202 487370)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 21.486404 + }, + { + "bron": "BAG/NWB", + "woonplaatscode": "3594", + "type": "weg", + "woonplaatsnaam": "Amsterdam", + "nwb_id": "032937", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "rdf_seealso": "http://bag.basisregistraties.overheid.nl/bag/id/openbare-ruimte/0363300000004690", + "weergavenaam": "Nieuwezijds Voorburgwal, Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "weg-11b9db917ce90372930af5e6a9188478", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89091865 52.37381873)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121203.803 487442.84)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 20.103004 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RC Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-5f1195a7f9fe6a99b1571d7c15c64138", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RC_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RC", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89522341 52.37696711)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121499.326 487791.141)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RD Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-89dbb53c07add38657bf17abe6dd49c4", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RD_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RD", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.8938645 52.3761153)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121406.149 487696.995)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RE Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-f303e0cf9b29083a2beb757476ce8948", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RE_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RE", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89252497 52.37521114)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121314.248 487597.017)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RG Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-e6324266fae865a1d66861a5118ff3af", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RG_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RG", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89177932 52.37453055)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121262.955 487521.639)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RH Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-57b324f3b15c70ac7a8641c10b318c6a", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RH_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RH", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89161743 52.37435875)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121251.8 487502.6)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RJ Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-def6647d79cbce522864726af4c2af74", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RJ_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RJ", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89133064 52.3739109)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121231.93 487452.904)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RK Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-1fbacacc892befcdaa4e46f475e5a16a", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RK_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RK", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.89097665 52.37221864)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121206.534 487264.783)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + }, + { + "bron": "BAG", + "woonplaatscode": "3594", + "type": "postcode", + "woonplaatsnaam": "Amsterdam", + "openbareruimtetype": "Weg", + "gemeentecode": "0363", + "weergavenaam": "Nieuwezijds Voorburgwal, 1012RL Amsterdam", + "straatnaam_verkort": "Nieuwezijds Voorburgwal", + "id": "pcd-540b9459499a7a25fa74d39a80072570", + "gemeentenaam": "Amsterdam", + "identificatie": "0363300000004690_1012RL_3594", + "openbareruimte_id": "0363300000004690", + "provinciecode": "PV27", + "postcode": "1012RL", + "provincienaam": "Noord-Holland", + "centroide_ll": "POINT(4.8911854 52.37137729)", + "provincieafkorting": "NH", + "centroide_rd": "POINT(121220.109 487171.074)", + "straatnaam": "Nieuwezijds Voorburgwal", + "score": 18.053778 + } + ] + } +} \ No newline at end of file diff --git a/test/fixtures/pdok_nl_no_results b/test/fixtures/pdok_nl_no_results new file mode 100644 index 000000000..dea509759 --- /dev/null +++ b/test/fixtures/pdok_nl_no_results @@ -0,0 +1,8 @@ +{ + "response": { + "numFound": 0, + "start": 0, + "maxScore": 21.486404, + "numFoundExact": true, + "docs": [] +} diff --git a/test/test_helper.rb b/test/test_helper.rb index a2e13d42c..d343543ff 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -252,6 +252,31 @@ def default_fixture_filename end end + require 'geocoder/lookups/ip2location_io' + class Ip2locationIo + private + def default_fixture_filename + "ip2location_io_8_8_8_8" + end + end + + require 'geocoder/lookups/ip2location_lite' + class Ip2locationLite + private + + remove_method(:results) + + def results query + return [] if query.to_s == "no results" + + if query.to_s == '127.0.0.1' + [{:country_short=>"-", :country_long=>"-", :region=>"-", :city=>"-", :latitude=>0.0, :longitude=>0.0, :zipcode=>"-", :timezone=>"-", :isp=>"Loopback", :domain=>"-", :netspeed=>"-", :iddcode=>"-", :areacode=>"-", :weatherstationcode=>"-", :weatherstationname=>"-", :mcc=>"-", :mnc=>"-", :mobilebrand=>"-", :elevation=>0, :usagetype=>"RSV", :addresstype=>"U", :category=>"IAB24", :district=>"-", :asn=>"-", :as=>"-"}] + elsif query.to_s == '8.8.8.8' + [{:country_short=>"US", :country_long=>"United States of America", :region=>"California", :city=>"Mountain View", :latitude=>37.40599060058594, :longitude=>-122.0785140991211, :zipcode=>"94043", :timezone=>"-07:00", :isp=>"Google LLC", :domain=>"google.com", :netspeed=>"T1", :iddcode=>"1", :areacode=>"650", :weatherstationcode=>"USCA0746", :weatherstationname=>"Mountain View", :mcc=>"-", :mnc=>"-", :mobilebrand=>"-", :elevation=>32, :usagetype=>"DCH", :addresstype=>"A", :category=>"IAB19-11", :district=>"San Diego County", :asn=>"15169", :as=>"Google LLC"}] + end + end + end + require 'geocoder/lookups/ipgeolocation' class Ipgeolocation private @@ -345,7 +370,6 @@ def results query end end - require 'geocoder/lookups/baidu' class Baidu private @@ -362,6 +386,14 @@ def default_fixture_filename end end + require 'geocoder/lookups/pdok_nl' + class PdokNl + private + def default_fixture_filename + "pdok_nl" + end + end + require 'geocoder/lookups/baidu_ip' class BaiduIp private diff --git a/test/unit/cache_test.rb b/test/unit/cache_test.rb index f58bc4f66..6b41895df 100644 --- a/test/unit/cache_test.rb +++ b/test/unit/cache_test.rb @@ -21,6 +21,7 @@ def test_second_occurrence_of_request_is_cache_hit # local, does not use cache l == :maxmind_local || l == :geoip2 || + l == :ip2location_lite || # uses the AWS gem, not HTTP requests with caching l == :amazon_location_service Geocoder.configure(:lookup => l) diff --git a/test/unit/error_handling_test.rb b/test/unit/error_handling_test.rb index c63ef2fcd..af7a06355 100644 --- a/test/unit/error_handling_test.rb +++ b/test/unit/error_handling_test.rb @@ -43,7 +43,6 @@ def test_never_raise_response_parse_error def test_always_raise_timeout_error Geocoder.configure(:always_raise => [Timeout::Error]) Geocoder::Lookup.all_services_with_http_requests.each do |l| - next if l == :maxmind_local || l == :geoip2 # local, does not use cache lookup = Geocoder::Lookup.get(l) set_api_key!(l) assert_raises Timeout::Error do @@ -55,7 +54,6 @@ def test_always_raise_timeout_error def test_always_raise_socket_error Geocoder.configure(:always_raise => [SocketError]) Geocoder::Lookup.all_services_with_http_requests.each do |l| - next if l == :maxmind_local || l == :geoip2 # local, does not use cache lookup = Geocoder::Lookup.get(l) set_api_key!(l) assert_raises SocketError do @@ -67,7 +65,6 @@ def test_always_raise_socket_error def test_always_raise_connection_refused_error Geocoder.configure(:always_raise => [Errno::ECONNREFUSED]) Geocoder::Lookup.all_services_with_http_requests.each do |l| - next if l == :maxmind_local || l == :geoip2 # local, does not use cache lookup = Geocoder::Lookup.get(l) set_api_key!(l) assert_raises Errno::ECONNREFUSED do @@ -79,7 +76,6 @@ def test_always_raise_connection_refused_error def test_always_raise_host_unreachable_error Geocoder.configure(:always_raise => [Errno::EHOSTUNREACH]) Geocoder::Lookup.all_services_with_http_requests.each do |l| - next if l == :maxmind_local || l == :geoip2 # local, does not use cache lookup = Geocoder::Lookup.get(l) set_api_key!(l) assert_raises Errno::EHOSTUNREACH do diff --git a/test/unit/lookup_test.rb b/test/unit/lookup_test.rb index dcd2ee8e0..7c59ced58 100644 --- a/test/unit/lookup_test.rb +++ b/test/unit/lookup_test.rb @@ -32,7 +32,7 @@ def test_search_returns_empty_array_when_no_results def test_query_url_contains_values_in_params_hash Geocoder::Lookup.all_services_except_test.each do |l| - next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipapi_com, :ipregistry, :ipstack, :postcodes_io, :uk_ordnance_survey_names, :amazon_location_service, :ipbase, :get_address_uk].include? l # does not use query string + next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipapi_com, :ipregistry, :ipstack, :postcodes_io, :uk_ordnance_survey_names, :amazon_location_service, :ipbase, :ip2location_lite, :get_address_uk].include? l # does not use query string set_api_key!(l) url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new( "test", :params => {:one_in_the_hand => "two in the bush"} diff --git a/test/unit/lookups/google_places_search_test.rb b/test/unit/lookups/google_places_search_test.rb index 817a220b9..d096c57fa 100644 --- a/test/unit/lookups/google_places_search_test.rb +++ b/test/unit/lookups/google_places_search_test.rb @@ -51,7 +51,7 @@ def test_google_places_search_query_url_always_uses_https def test_google_places_search_query_url_contains_every_field_available_by_default url = lookup.query_url(Geocoder::Query.new("some-address")) - fields = %w[id reference business_status formatted_address geometry icon name + fields = %w[business_status formatted_address geometry icon name photos place_id plus_code types opening_hours price_level rating user_ratings_total] assert_match(/fields=#{fields.join('%2C')}/, url) diff --git a/test/unit/lookups/ip2location_io_test.rb b/test/unit/lookups/ip2location_io_test.rb new file mode 100644 index 000000000..b85e041de --- /dev/null +++ b/test/unit/lookups/ip2location_io_test.rb @@ -0,0 +1,24 @@ +# encoding: utf-8 +require 'test_helper' + +class Ip2locationIoTest < GeocoderTestCase + + def setup + super + Geocoder.configure(ip_lookup: :ip2location_io) + set_api_key!(:ip2location_io) + end + + def test_ip2location_io_query_url + query = Geocoder::Query.new('8.8.8.8') + assert_equal 'http://api.ip2location.io/?ip=8.8.8.8&key=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', query.url + end + + def test_ip2location_io_lookup_address + result = Geocoder.search("8.8.8.8").first + assert_equal "US", result.country_code + assert_equal "United States of America", result.country_name + assert_equal "California", result.region_name + assert_equal "Mountain View", result.city_name + end +end diff --git a/test/unit/lookups/ip2location_lite_test.rb b/test/unit/lookups/ip2location_lite_test.rb new file mode 100644 index 000000000..8ff9f695a --- /dev/null +++ b/test/unit/lookups/ip2location_lite_test.rb @@ -0,0 +1,14 @@ +# encoding: utf-8 +require 'test_helper' + +class Ip2locationLiteTest < GeocoderTestCase + def setup + super + Geocoder.configure(ip_lookup: :ip2location_lite, ip2location_lite: { file: File.join('folder', 'test_file') }) + end + + def test_loopback + result = Geocoder.search('127.0.0.1').first + assert_equal '', result.country_short + end +end \ No newline at end of file diff --git a/test/unit/lookups/pdok_nl_test.rb b/test/unit/lookups/pdok_nl_test.rb new file mode 100644 index 000000000..bb53adbcd --- /dev/null +++ b/test/unit/lookups/pdok_nl_test.rb @@ -0,0 +1,25 @@ +# encoding: utf-8 +require 'test_helper' + +class PdokNlTest < GeocoderTestCase + + def setup + super + Geocoder.configure(lookup: :pdok_nl) + end + + def test_result_components + result = Geocoder.search('Nieuwezijds Voorburgwal 147, Amsterdam').first + + assert_equal result.street, 'Nieuwezijds Voorburgwal' + assert_equal result.street_number, '147' + assert_equal result.city, 'Amsterdam' + assert_equal result.postal_code, '1012RJ' + assert_equal result.address, 'Nieuwezijds Voorburgwal 147, 1012RJ Amsterdam' + assert_equal result.province, 'Noord-Holland' + assert_equal result.province_code, 'PV27' + assert_equal result.country_code, 'NL' + assert_equal result.latitude, 52.37316398 + assert_equal result.longitude, 4.89089949 + end +end diff --git a/test/unit/result_test.rb b/test/unit/result_test.rb index 6746a10cc..63293ccfd 100644 --- a/test/unit/result_test.rb +++ b/test/unit/result_test.rb @@ -8,6 +8,8 @@ def test_forward_geocoding_result_has_required_attributes next if [ :get_address_uk, # Doesn't search by coordinates :ip2location, # has pay-per-attribute pricing model + :ip2location_io, # has pay-per-attribute pricing model + :ip2location_lite, # no forward geocoding :twogis, # cant find 'Madison Square Garden' ].include?(l) @@ -22,6 +24,8 @@ def test_reverse_geocoding_result_has_required_attributes Geocoder::Lookup.all_services_except_test.each do |l| next if [ :ip2location, # has pay-per-attribute pricing model + :ip2location_io, # has pay-per-attribute pricing model + :ip2location_lite, # no reverse geocoding :nationaal_georegister_nl, # no reverse geocoding :melissa_street, # reverse geocoding not implemented :twogis, # cant find 'Madison Square Garden'