refactor: IpLookup lazy load reader
This commit is contained in:
@@ -30,7 +30,7 @@ module App::Controllers
|
||||
|
||||
click = App::Models::Click.new
|
||||
click.link_id = link_id
|
||||
click.country = client_ip ? IpLookup.country(client_ip).try(&.code) : nil
|
||||
click.country = client_ip ? IpLookup.country(client_ip) : nil
|
||||
click.user_agent = user_agent_str
|
||||
click.browser = ua_parser.try(&.family)
|
||||
click.os = ua_parser.try(&.os.try(&.family))
|
||||
|
||||
+28
-31
@@ -1,48 +1,45 @@
|
||||
require "maxminddb"
|
||||
require "log"
|
||||
|
||||
struct IpLookup
|
||||
MMDB_PATH = "data/GeoLite2-Country.mmdb"
|
||||
module App::Lib
|
||||
struct IpLookup
|
||||
MMDB_PATH = "data/GeoLite2-Country.mmdb"
|
||||
|
||||
record Country, code : String? = nil, name : String? = nil
|
||||
@@reader : MaxMindDB::Reader? = nil
|
||||
@@reader_mutex = Mutex.new
|
||||
|
||||
def self.country(ip_address : String) : Country?
|
||||
return nil if ip_address == "Unknown" || ip_address.empty?
|
||||
private def self.get_reader : MaxMindDB::Reader
|
||||
@@reader_mutex.synchronize do
|
||||
@@reader ||= MaxMindDB.open(MMDB_PATH)
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
reader = MaxMindDB.open(MMDB_PATH)
|
||||
lookup = reader.get(ip_address)
|
||||
def self.country(ip_address : String) : String?
|
||||
return nil if ip_address == "Unknown" || ip_address.empty?
|
||||
|
||||
country_code = lookup["country"]?.try &.["iso_code"]?.try &.as_s
|
||||
country_name = lookup["country"]?.try &.["names"]?.try &.["en"]?.try &.as_s
|
||||
|
||||
if country_code || country_name
|
||||
Country.new(
|
||||
code: country_code,
|
||||
name: country_name
|
||||
)
|
||||
else
|
||||
begin
|
||||
lookup = get_reader.get(ip_address)
|
||||
lookup["country"]?.try &.["iso_code"]?.try &.as_s
|
||||
rescue ex
|
||||
Log.error { "IP lookup failed: #{ex.message}" }
|
||||
nil
|
||||
end
|
||||
rescue ex
|
||||
Log.error { "IP lookup failed: #{ex.message}" }
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def self.ip_from_address(address_string : String?) : String?
|
||||
return nil if address_string.nil?
|
||||
def self.ip_from_address(address_string : String?) : String?
|
||||
return nil if address_string.nil?
|
||||
|
||||
if address_string.includes?('[') # IPv6 with port: [2001:db8::1]:8080
|
||||
address_string.split(']').first.sub('[', '\'')
|
||||
elsif address_string.includes?(':')
|
||||
if address_string.count(':') > 1 # IPv6 without port
|
||||
if address_string.includes?('[') # IPv6 with port: [2001:db8::1]:8080
|
||||
address_string.split(']').first.sub('[', '\'')
|
||||
elsif address_string.includes?(':')
|
||||
if address_string.count(':') > 1 # IPv6 without port
|
||||
address_string
|
||||
else # IPv4 with port: 192.168.1.1:8080
|
||||
address_string.split(':').first
|
||||
end
|
||||
else # Address without port
|
||||
address_string
|
||||
else # IPv4 with port: 192.168.1.1:8080
|
||||
address_string.split(':').first
|
||||
end
|
||||
else # Address without port
|
||||
address_string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user