diff --git a/README_API_GUIDE.md b/README_API_GUIDE.md index e9c0c0a8ef164c293e72c5b76bf74e4eced28a9a..1a6ce9dbdedb835deb6413b695711811382128cc 100644 --- a/README_API_GUIDE.md +++ b/README_API_GUIDE.md @@ -463,6 +463,17 @@ IP Address Lookups * **Terms of Service**: https://ipdata.co/terms.html * **Limitations**: ? +### IP2Location Web Service (`:ip2location_api`) + +* **API key**: optional, see: https://www.ip2location.com/web-service +* **Quota**: 20 query/day (up to 100k credits with paid API key) +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: https://www.ip2location.com/web-service +* **Terms of Service**: https://www.ip2location.com/web-service +* **Notes**: To use IP2Location Web Service with API Key set `Geocoder.configure(:ip_lookup => :ip2location_api, :api_key => "IP2LOCATION_WEB_SERVICE_API_KEY")`. Supports the optional param :package with `Geocoder.configure(:ip2location_api => {:package => "WSX"})` (see API documentation for package offered in details). + Local IP Address Lookups ------------------------ diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index df284da443ea109e283a54b5f19b505bfb9e7ec3..e9802d073ab5a76f68c434eaf60f2e45570c6cfe 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -73,6 +73,7 @@ module Geocoder :ipdata_co, :db_ip_com, :ipstack, + :ip2location_api, ] end diff --git a/lib/geocoder/lookups/ip2location_api.rb b/lib/geocoder/lookups/ip2location_api.rb new file mode 100644 index 0000000000000000000000000000000000000000..5650fe743bb9c4554e1473af55eedd8fe3cff385 --- /dev/null +++ b/lib/geocoder/lookups/ip2location_api.rb @@ -0,0 +1,73 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ip2location_api' + +module Geocoder::Lookup + class Ip2locationApi < Base + + def name + "IP2LocationApi" + end + + def query_url(query) + api_key = configuration.api_key ? configuration.api_key : "demo" + url_ = "#{protocol}://api.ip2location.com/?ip=#{query.sanitized_text}&key=#{api_key}&format=json" + + if (params = url_query_string(query)) && !params.empty? + url_ + "&" + params + else + url_ + end + 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["response"] == "INVALID ACCOUNT" + raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT") + return [] + else + return [doc] + end + end + + def reserved_result(query) + { + "country_code" => "INVALID IP ADDRESS", + "country_name" => "INVALID IP ADDRESS", + "region_name" => "INVALID IP ADDRESS", + "city_name" => "INVALID IP ADDRESS", + "latitude" => "INVALID IP ADDRESS", + "longitude" => "INVALID IP ADDRESS", + "zip_code" => "INVALID IP ADDRESS", + "time_zone" => "INVALID IP ADDRESS", + "isp" => "INVALID IP ADDRESS", + "domain" => "INVALID IP ADDRESS", + "net_speed" => "INVALID IP ADDRESS", + "idd_code" => "INVALID IP ADDRESS", + "area_code" => "INVALID IP ADDRESS", + "weather_station_code" => "INVALID IP ADDRESS", + "weather_station_name" => "INVALID IP ADDRESS", + "mcc" => "INVALID IP ADDRESS", + "mnc" => "INVALID IP ADDRESS", + "mobile_brand" => "INVALID IP ADDRESS", + "elevation" => "INVALID IP ADDRESS", + "usage_type" => "INVALID IP ADDRESS" + } + end + + def query_url_params(query) + params = {} + params.merge!(package: configuration[:package]) if configuration.has_key?(:package) + params.merge(super) + end + + end +end diff --git a/lib/geocoder/results/ip2location_api.rb b/lib/geocoder/results/ip2location_api.rb new file mode 100644 index 0000000000000000000000000000000000000000..0915805417cae054851d22a6297c56057acc51a7 --- /dev/null +++ b/lib/geocoder/results/ip2location_api.rb @@ -0,0 +1,101 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Ip2locationApi < Base + + def address(format = :full) + "#{city_name} #{zip_code}, #{country_name}".sub(/^[ ,]*/, '') + end + + def country_code + country_code + end + + def country_name + country_name + end + + def region_name + region_name + end + + def city_name + city_name + end + + def latitude + latitude + end + + def longitude + longitude + end + + def zip_code + zip_code + end + + def time_zone + time_zone + end + + def isp + isp + end + + def domain + domain + end + + def net_speed + net_speed + end + + def idd_code + idd_code + end + + def area_code + area_code + end + + def weather_station_code + weather_station_code + end + + def weather_station_name + weather_station_name + end + + def mcc + mcc + end + + def mnc + mnc + end + + def mobile_brand + mobile_brand + end + + def elevation + elevation + end + + def usage_type + usage_type + end + + def self.response_attributes + %w[country_code country_name region_name city_name latitude longitude zip_code time_zone isp domain net_speed idd_code area_code weather_station_code weather_station_name mcc mnc mobile_brand elevation usage_type] + end + + response_attributes.each do |attribute| + define_method attribute do + @data[attribute] + end + end + + end +end diff --git a/test/fixtures/ip2location_api_8_8_8_8 b/test/fixtures/ip2location_api_8_8_8_8 new file mode 100644 index 0000000000000000000000000000000000000000..84d967d69aa94fb085c57e9e75b9e161a178a8b2 --- /dev/null +++ b/test/fixtures/ip2location_api_8_8_8_8 @@ -0,0 +1,22 @@ +{ + "country_code":"US", + "country_name":"United States", + "region_name":"California", + "city_name":"Mountain View", + "latitude":"37.405992", + "longitude":"-122.078515", + "zip_code":"94043", + "time_zone":"-07:00", + "isp":"Google LLC", + "domain":"google.com", + "net_speed":"T1", + "idd_code":"1", + "area_code":"650", + "weather_station_code":"USCA0746", + "weather_station_name":"Mountain View", + "mcc":"-", + "mnc":"-", + "mobile_brand":"-", + "elevation":"31", + "usage_type":"DCH" +} \ No newline at end of file diff --git a/test/fixtures/ip2location_api_invalid_api_key b/test/fixtures/ip2location_api_invalid_api_key new file mode 100644 index 0000000000000000000000000000000000000000..698205b4f39d51435eaf1b9844a13634b6e02764 --- /dev/null +++ b/test/fixtures/ip2location_api_invalid_api_key @@ -0,0 +1,3 @@ +{ + "response":"INVALID ACCOUNT" +} \ No newline at end of file diff --git a/test/unit/lookups/ip2location_api_test.rb b/test/unit/lookups/ip2location_api_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..43f3c1284d71dc2055d62f59bcd39c3fcd865c7b --- /dev/null +++ b/test/unit/lookups/ip2location_api_test.rb @@ -0,0 +1,25 @@ +# encoding: utf-8 +require 'test_helper' + +class Ip2locationApiTest < GeocoderTestCase + + def test_ip2location_api_lookup_address + Geocoder.configure(:ip_lookup => :ip2location_api) + result = Geocoder.search("8.8.8.8").first + assert_equal "US", result.country_code + end + + def test_ip2location_api_lookup_loopback_address + Geocoder.configure(:ip_lookup => :ip2location_api) + result = Geocoder.search("127.0.0.1").first + assert_equal "INVALID IP ADDRESS", result.country_code + end + + def test_ip2location_api_extra_data + Geocoder.configure(:ip_lookup => :ip2location_api, :ip2location_api => {:package => "WS3"}) + result = Geocoder.search("8.8.8.8").first + assert_equal "United States", result.country_name + assert_equal "California", result.region_name + assert_equal "Mountain View", result.city_name + end +end