diff --git a/README_API_GUIDE.md b/README_API_GUIDE.md index cf1a5ebc5..01547a688 100644 --- a/README_API_GUIDE.md +++ b/README_API_GUIDE.md @@ -474,6 +474,37 @@ IP Address Lookups * **Terms of Service**: https://www.ip2location.com/web-service * **Notes**: With the non-free version, specify your desired package: `Geocoder.configure(ip2location: {package: "WSX"})` (see API documentation for package details). +### IPInfoDB (`:ipinfodb`) + +* **API key**: required +* **Quota**: 2 queries per second +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: https://www.ipinfodb.com/api +* **Terms of Service**: https://www.ipinfodb.com/api + +### Ipregistry (`:ipregistry`) + +* **API key**: required (see https://ipregistry.co) +* **Quota**: first 100,000 requests are free, then you pay per request (see https://ipregistry.co/pricing) +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: https://ipregistry.co/docs +* **Terms of Service**: https://ipregistry.co/terms + +### Ipgeolocation (`:ipgeolocation`) + +* **API key**: required (see https://ipgeolocation.io/pricing) +* **Quota**: 1500/day (with free API Key) +* **Region**: world +* **SSL support**: yes +* **Languages**: English, German, Russian, Japanese, French, Chinese, Spanish, Czech, Italian +* **Documentation**: https://ipgeolocation.io/documentation +* **Terms of Service**: https://ipgeolocation/tos +* **Notes**: To use Ipgeolocation set `Geocoder.configure(ip_lookup: :ipgeolocation, api_key: "your_ipgeolocation_api_key", use_https:true)`. Supports the optional params: { excludes: "continent_code"}, {fields: "geo"}, {lang: "ru"}, {output: "xml"}, {include: "hostname"}, {ip: "174.7.116.0"}) (see API documentation for details). + Local IP Address Lookups ------------------------ diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index 5ccae1022..70a87e788 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -73,7 +73,9 @@ def ip_services :ipdata_co, :db_ip_com, :ipstack, - :ip2location + :ip2location, + :ipinfodb, + :ipgeolocation ] end diff --git a/lib/geocoder/lookups/ipinfodb.rb b/lib/geocoder/lookups/ipinfodb.rb new file mode 100644 index 000000000..4fc9be9fb --- /dev/null +++ b/lib/geocoder/lookups/ipinfodb.rb @@ -0,0 +1,46 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ipinfodb' + +module Geocoder::Lookup + class Ipinfodb < Base + + def name + "IPInfoDBApi" + end + + def query_url(query) + url = "#{protocol}://api.ipinfodb.com/v3/ip-city/?key=#{configuration.api_key}&ip=#{query.sanitized_text}&format=json" + end + + def supported_protocols + [:http, :https] + end + + private # ---------------------------------------------------------------- + + def results(query) + return [reserved_result(query.text)] if query.loopback_ip_address? + return [] unless doc = fetch_data(query) + if doc["statusMessage"] == "Invalid API key." + raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key.") + return [] + else + return [doc] + end + end + + def reserved_result(query) + { + "countryCode" => "-", + "countryName" => "-", + "regionName" => "-", + "cityName" => "-", + "zipCode" => "-", + "latitude" => "0", + "longitude" => "0", + "timeZone" => "-" + } + end + + end +end diff --git a/lib/geocoder/results/ipinfodb.rb b/lib/geocoder/results/ipinfodb.rb new file mode 100644 index 000000000..209082635 --- /dev/null +++ b/lib/geocoder/results/ipinfodb.rb @@ -0,0 +1,20 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Ipinfodb < Base + + def address(format = :full) + "#{cityName} #{zipCode}, #{countryName}".sub(/^[ ,]*/, '') + end + + def self.response_attributes + %w[countryCode countryName regionName cityName zipCode latitude longitude timeZone] + end + + response_attributes.each do |attr| + define_method attr do + @data[attr] || "" + end + end + end +end diff --git a/test/fixtures/ipinfodb_8_8_8_8 b/test/fixtures/ipinfodb_8_8_8_8 new file mode 100644 index 000000000..515a56086 --- /dev/null +++ b/test/fixtures/ipinfodb_8_8_8_8 @@ -0,0 +1,13 @@ +{ + "statusCode" : "OK", + "statusMessage" : "", + "ipAddress" : "8.8.8.8", + "countryCode" : "US", + "countryName" : "United States", + "regionName" : "California", + "cityName" : "Mountain View", + "zipCode" : "94043", + "latitude" : "37.406", + "longitude" : "-122.079", + "timeZone" : "-07:00" +} \ No newline at end of file diff --git a/test/fixtures/ipinfodb_invalid_api_key b/test/fixtures/ipinfodb_invalid_api_key new file mode 100644 index 000000000..a686ce1cb --- /dev/null +++ b/test/fixtures/ipinfodb_invalid_api_key @@ -0,0 +1,13 @@ +{ + "statusCode" : "ERROR", + "statusMessage" : "Invalid API key.", + "ipAddress" : "", + "countryCode" : "", + "countryName" : "", + "regionName" : "", + "cityName" : "", + "zipCode" : "", + "latitude" : "0", + "longitude" : "0", + "timeZone" : "" +} \ No newline at end of file diff --git a/test/fixtures/ipinfodb_no_results b/test/fixtures/ipinfodb_no_results new file mode 100644 index 000000000..e69de29bb diff --git a/test/test_helper.rb b/test/test_helper.rb index d6243a919..815755ccd 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -225,6 +225,22 @@ def default_fixture_filename end end + require 'geocoder/lookups/ipinfodb' + class Ipinfodb + private + def default_fixture_filename + "ipinfodb_8_8_8_8" + end + end + + require 'geocoder/lookups/ipgeolocation' + class Ipgeolocation + private + def default_fixture_filename + "ipgeolocation_103_217_177_217" + end + end + require 'geocoder/lookups/ipstack' class Ipstack private diff --git a/test/unit/lookups/ipinfodb_test.rb b/test/unit/lookups/ipinfodb_test.rb new file mode 100644 index 000000000..7397dab68 --- /dev/null +++ b/test/unit/lookups/ipinfodb_test.rb @@ -0,0 +1,22 @@ +# encoding: utf-8 +require 'test_helper' + +class IpinfodbTest < GeocoderTestCase + + def setup + Geocoder.configure(:ip_lookup => :ipinfodb, :api_key => 'IPINFODB_API_KEY') + end + + def test_ipinfodb_lookup_address + result = Geocoder.search("8.8.8.8").first + assert_equal "US", result.countryCode + assert_equal "United States", result.countryName + assert_equal "California", result.regionName + assert_equal "Mountain View", result.cityName + end + + def test_ipinfodb_lookup_loopback_address + result = Geocoder.search("127.0.0.1").first + assert_equal "-", result.countryCode + end +end diff --git a/test/unit/result_test.rb b/test/unit/result_test.rb index eeb579ee8..06b3be0cf 100644 --- a/test/unit/result_test.rb +++ b/test/unit/result_test.rb @@ -6,6 +6,7 @@ class ResultTest < GeocoderTestCase def test_forward_geocoding_result_has_required_attributes Geocoder::Lookup.all_services_except_test.each do |l| next if l == :ip2location # has pay-per-attribute pricing model + next if l == :ipinfodb Geocoder.configure(:lookup => l) set_api_key!(l) result = Geocoder.search("Madison Square Garden").first @@ -16,6 +17,8 @@ def test_forward_geocoding_result_has_required_attributes def test_reverse_geocoding_result_has_required_attributes Geocoder::Lookup.all_services_except_test.each do |l| next if l == :ip2location # has pay-per-attribute pricing model + next if l == :ipinfodb + next if l == :nationaal_georegister_nl # no reverse geocoding Geocoder.configure(:lookup => l) set_api_key!(l) result = Geocoder.search([45.423733, -75.676333]).first