lib/geokit/geocoders/base_ip.rb
module Geokit
module Geocoders
class BaseIpGeocoder < Geocoder
# A number of non-routable IP ranges.
#
# --
# Sources for these:
# RFC 3330: Special-Use IPv4 Addresses
# The bogon list: http://www.cymru.com/Documents/bogon-list.html
NON_ROUTABLE_IP_RANGES = [
IPAddr.new('0.0.0.0/8'), # "This" Network
IPAddr.new('10.0.0.0/8'), # Private-Use Networks
IPAddr.new('14.0.0.0/8'), # Public-Data Networks
IPAddr.new('127.0.0.0/8'), # Loopback
IPAddr.new('169.254.0.0/16'), # Link local
IPAddr.new('172.16.0.0/12'), # Private-Use Networks
IPAddr.new('192.0.2.0/24'), # Test-Net
IPAddr.new('192.168.0.0/16'), # Private-Use Networks
IPAddr.new('198.18.0.0/15'), # Network Interconnect Device Benchmark Testing
IPAddr.new('224.0.0.0/4'), # Multicast
IPAddr.new('240.0.0.0/4') # Reserved for future use
].freeze
def self.valid_ip?(ip)
ip?(ip) && !private_ip_address?(ip)
end
def self.ip?(ip)
/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
end
def self.process(format, ip)
return GeoLoc.new unless valid_ip?(ip)
super(format, submit_url(ip))
end
# Checks whether the IP address belongs to a private address range.
#
# This function is used to reduce the number of useless queries made to
# the geocoding service. Such queries can occur frequently during
# integration tests.
def self.private_ip_address?(ip)
NON_ROUTABLE_IP_RANGES.any? { |range| range.include?(ip) }
end
end
end
end