diff --git a/README_API_GUIDE.md b/README_API_GUIDE.md index 1dfce2a59..3ac7c5ec9 100644 --- a/README_API_GUIDE.md +++ b/README_API_GUIDE.md @@ -655,6 +655,19 @@ IP Address Lookups * **Documentation**: https://ipinfo.io/developers * **Terms of Service**: https://ipinfo.io/terms-of-service +### IPInfo.io Lite (`:ipinfo_io_lite`) + +A free-tier API access plan, which includes unlimited country-level geolocation information and unlimited basic ASN information. Geolocation information provided by the Lite API service includes country and continent information, while ASN information includes ASN, organization name, and domain name. + +* **API key**: required +* **Quota**: none +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: https://ipinfo.io/developers/lite-api +* **Terms of Service**: https://ipinfo.io/terms-of-service +* **Limitations**: country-level geolocation information and basic ASN information only + ### IPQualityScore (`:ipqualityscore`) * **API key**: required - see https://www.ipqualityscore.com/free-ip-lookup-proxy-vpn-test diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index bef2f3494..f0cba7fda 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -87,6 +87,7 @@ def ip_services :pointpin, :maxmind_geoip2, :ipinfo_io, + :ipinfo_io_lite, :ipregistry, :ipapi_com, :ipdata_co, diff --git a/lib/geocoder/lookups/ipinfo_io_lite.rb b/lib/geocoder/lookups/ipinfo_io_lite.rb new file mode 100644 index 000000000..6de522330 --- /dev/null +++ b/lib/geocoder/lookups/ipinfo_io_lite.rb @@ -0,0 +1,42 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ipinfo_io_lite' + +module Geocoder::Lookup + class IpinfoIoLite < Base + def name + 'Ipinfo.io Lite' + end + + private # --------------------------------------------------------------- + + def base_query_url(query) + url = "#{protocol}://api.ipinfo.io/lite/#{query.sanitized_text}" + url << '?' if configuration.api_key + url + 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? + + if !(doc = fetch_data(query)).is_a?(Hash) or doc['error'] + [] + else + [doc] + end + end + + def reserved_result(ip) + { + 'ip' => ip, + 'bogon' => true + } + end + + def query_url_params(query) + { + token: configuration.api_key + }.merge(super) + end + end +end diff --git a/lib/geocoder/results/ipinfo_io_lite.rb b/lib/geocoder/results/ipinfo_io_lite.rb new file mode 100644 index 000000000..2b1d28644 --- /dev/null +++ b/lib/geocoder/results/ipinfo_io_lite.rb @@ -0,0 +1,16 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class IpinfoIoLite < Base + + def self.response_attributes + %w(ip asn as_name as_domain country country_code continent continent_code) + end + + response_attributes.each do |a| + define_method a do + @data[a] + end + end + end +end diff --git a/test/fixtures/ipinfo_io_lite_8_8_8_8 b/test/fixtures/ipinfo_io_lite_8_8_8_8 new file mode 100644 index 000000000..29487555a --- /dev/null +++ b/test/fixtures/ipinfo_io_lite_8_8_8_8 @@ -0,0 +1,10 @@ +{ + "ip": "8.8.8.8", + "asn": "AS15169", + "as_name": "Google LLC", + "as_domain": "google.com", + "country_code": "US", + "country": "United States", + "continent": "North America", + "continent_code": "NA" +} diff --git a/test/fixtures/ipinfo_io_lite_no_results b/test/fixtures/ipinfo_io_lite_no_results new file mode 100644 index 000000000..e69de29bb diff --git a/test/test_helper.rb b/test/test_helper.rb index cf63d39a2..12fe5c8a2 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -478,6 +478,14 @@ def default_fixture_filename end end + require 'geocoder/lookups/ipinfo_io_lite' + class IpinfoIoLite + private + def default_fixture_filename + "ipinfo_io_lite_8_8_8_8" + end + end + require 'geocoder/lookups/ipregistry' class Ipregistry private diff --git a/test/unit/lookup_test.rb b/test/unit/lookup_test.rb index ab4dc0b5c..91329edcb 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, :ip2location_lite].include? l # does not use query string + next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipinfo_io_lite, :ipapi_com, :ipregistry, :ipstack, :postcodes_io, :uk_ordnance_survey_names, :amazon_location_service, :ipbase, :ip2location_lite].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/ipinfo_io_lite_test.rb b/test/unit/lookups/ipinfo_io_lite_test.rb new file mode 100644 index 000000000..c48d89ecd --- /dev/null +++ b/test/unit/lookups/ipinfo_io_lite_test.rb @@ -0,0 +1,26 @@ +require 'test_helper' + +class IpinfoIoLiteTest < GeocoderTestCase + def test_ipinfo_io_lite_lookup_loopback_address + Geocoder.configure(ip_lookup: :ipinfo_io_lite) + result = Geocoder.search('127.0.0.1').first + assert_equal '127.0.0.1', result.ip + end + + def test_ipinfo_io_lite_lookup_private_address + Geocoder.configure(ip_lookup: :ipinfo_io_lite) + result = Geocoder.search('172.19.0.1').first + assert_equal '172.19.0.1', result.ip + end + + def test_ipinfo_io_lite_extra_attributes + Geocoder.configure(ip_lookup: :ipinfo_io_lite, use_https: true) + result = Geocoder.search('8.8.8.8').first + assert_equal '8.8.8.8', result.ip + assert_equal 'US', result.country_code + assert_equal 'United States', result.country + assert_equal 'North America', result.continent + assert_equal 'NA', result.continent_code + assert_equal 'Google LLC', result.as_name + end +end diff --git a/test/unit/result_test.rb b/test/unit/result_test.rb index 78097abe2..4de8159dd 100644 --- a/test/unit/result_test.rb +++ b/test/unit/result_test.rb @@ -9,6 +9,7 @@ def test_forward_geocoding_result_has_required_attributes :ip2location, # has pay-per-attribute pricing model :ip2location_io, # has pay-per-attribute pricing model :ip2location_lite, # no forward geocoding + :ipinfo_io_lite, # does not support exact location :twogis, # cant find 'Madison Square Garden' ].include?(l) @@ -26,6 +27,7 @@ def test_reverse_geocoding_result_has_required_attributes :ip2location, # has pay-per-attribute pricing model :ip2location_io, # has pay-per-attribute pricing model :ip2location_lite, # no reverse geocoding + :ipinfo_io_lite, # no reverse geocoding :nationaal_georegister_nl, # no reverse geocoding :melissa_street, # reverse geocoding not implemented :twogis, # cant find 'Madison Square Garden'