Skip to content

Commit

Permalink
Add IP2Location.io API (#1631)
Browse files Browse the repository at this point in the history
Add IP2Location.io API
  • Loading branch information
ip2location authored Sep 5, 2023
1 parent b546dd6 commit cf000b3
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 1 deletion.
10 changes: 10 additions & 0 deletions README_API_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,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
------------------------
Expand Down
3 changes: 2 additions & 1 deletion lib/geocoder/lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ def ip_services
:ip2location,
:ipgeolocation,
:ipqualityscore,
:ipbase
:ipbase,
:ip2location_io
]
end

Expand Down
62 changes: 62 additions & 0 deletions lib/geocoder/lookups/ip2location_io.rb
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions lib/geocoder/results/ip2location_io.rb
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions test/fixtures/ip2location_io_8_8_8_8
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 6 additions & 0 deletions test/fixtures/ip2location_io_invalid_api_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"error": {
"error_code": 10000,
"error_message": "Invalid API key or insufficient query."
}
}
Empty file.
8 changes: 8 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,14 @@ 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/ipgeolocation'
class Ipgeolocation
private
Expand Down
24 changes: 24 additions & 0 deletions test/unit/lookups/ip2location_io_test.rb
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions test/unit/result_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def test_forward_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
:twogis, # cant find 'Madison Square Garden'
].include?(l)

Expand All @@ -21,6 +22,7 @@ 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
:nationaal_georegister_nl, # no reverse geocoding
:melissa_street, # reverse geocoding not implemented
:twogis, # cant find 'Madison Square Garden'
Expand Down

0 comments on commit cf000b3

Please sign in to comment.