geoip_whois_asn_country 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9cecafa6e6059a81d3f208c39aca786852eabedaa77e21fdef3f9b4e1904af2c
4
+ data.tar.gz: 3b2920f165960fb295c102fea0d4128d3d62151e3a8462c44a5c672017769498
5
+ SHA512:
6
+ metadata.gz: 9089baf7322337e7671abdb35558f01a02b0333a385917c14db6c4249191aa1ec24d61e2d4e23ce34b743e9c53a565e6896a891f687e3b3b26ed7d3597c75651
7
+ data.tar.gz: '01857dec38fb490b811aaf5670ac29c0d3d686a80cc9cb02927def150bc2607d576f771f1afbad63946fde13a5500f34f13449d3b720dfc4047936157ff1be91'
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in geoip_whois_asn_country.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+ gem 'pry'
10
+ gem 'steep'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Stefan Wienert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # GeoipWhoisAsnCountry
2
+
3
+ Uses the node package "@ip-location-db/geo-whois-asn-country" to build a ruby structure for efficient lookup of IP -> country both for IPv4 and IPv6.
4
+
5
+
6
+ ## Installation
7
+
8
+ Install the gem and add to the application's Gemfile by executing:
9
+
10
+ ```bash
11
+ bundle add geoip_whois_asn_country
12
+ yarn add @ip-location-db/geo-whois-asn-country
13
+ ```
14
+
15
+
16
+ ## Usage
17
+
18
+
19
+
20
+ ```ruby
21
+ require 'geoip_whois_asn_country'
22
+
23
+ # First run will take a couple of seconds and build the ruby strucutre
24
+ # and cache it into tmp/cache/geoip-country-cache
25
+ country_code = GeoIpCountry.lookup('1.2.3.4')
26
+ => :CN
27
+
28
+ country_code = GeoIpCountry.lookup('2001:db8::')
29
+ => :FI
30
+
31
+
32
+ GeoipWhoisAsnCountry.configure do |config|
33
+ config.cache_path = "tmp/cache/geoip-country-cache"
34
+ config.ipv4_num_csv_path = "./node_modules/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv4-num.csv"
35
+ config.ipv6_num_csv_path = "./node_modules/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv6-num.csv"
36
+ end
37
+ ```
38
+
39
+
40
+ ## Resource consumption
41
+
42
+ On a MacBook M2 I get the following results:
43
+
44
+ ```bash
45
+ GeoIP-Whois-ASN-Country: first load + cache
46
+ Took: 3.812936 0.039471 3.852407 ( 3.852622)
47
+ Residual Memory consumption: 17.94025993347168 MB
48
+ Starting: Cached load from Marshalled Data
49
+ Took: 0.340433 0.040012 0.380445 ( 0.380435)
50
+ Residual Memory consumption: 17.76226043701172 MB
51
+ Starting: Lookup of 10,000 random Ips
52
+ Took: 0.041649 0.000000 0.041649 ( 0.041644)
53
+ Residual Memory consumption: 0.00020599365234375 MB
54
+ ```
55
+
56
+
57
+ ## License
58
+
59
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/Steepfile ADDED
@@ -0,0 +1,14 @@
1
+ D = Steep::Diagnostic
2
+ target :lib do
3
+ signature 'sig'
4
+
5
+ check 'test/benchmark.rb'
6
+
7
+ library 'singleton'
8
+ library 'ipaddr'
9
+ library 'socket'
10
+ library 'objspace'
11
+ library 'benchmark'
12
+
13
+ configure_code_diagnostics(D::Ruby.strict)
14
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoipWhoisAsnCountry
4
+ VERSION = "0.2.0"
5
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "geoip_whois_asn_country/version"
4
+ require 'singleton'
5
+
6
+ module GeoipWhoisAsnCountry
7
+ def self.lookup(ip_address)
8
+ GeoIpCountry._lookup(ip_address)
9
+ end
10
+
11
+ def self.configure(&block)
12
+ block.call(GeoIpCountry)
13
+ Singleton.__init__(GeoIpCountry)
14
+ nil
15
+ end
16
+
17
+ class GeoIpCountry
18
+ include Singleton
19
+
20
+ class << self
21
+ attr_accessor :ipv4_num_csv_path, :ipv6_num_csv_path, :cache_path
22
+ end
23
+ self.ipv4_num_csv_path = "./node_modules/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv4-num.csv"
24
+ self.ipv6_num_csv_path = "./node_modules/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv6-num.csv"
25
+ self.cache_path = "tmp/cache/geoip-country-cache"
26
+ self.cache_time = 60 * 60 * 24
27
+
28
+ def self._lookup(ip)
29
+ if !@singleton__instance__ || @singleton__instance__.instance_variables.length == 0
30
+ if File.exist?(cache_path) && File.mtime(cache_path) > Time.now - cache_time
31
+ @singleton__instance__ = load_from_cache
32
+ else
33
+ # puts "GeoIP-Whois-ASN-Country: first load + cache"
34
+ instance.load_csvs
35
+ cache!
36
+ end
37
+ end
38
+ instance._lookup(ip)
39
+ end
40
+
41
+ def _dump(depth)
42
+ Marshal.dump({
43
+ ipv4_map: @ipv4_map,
44
+ ipv4_sorted_keys: @ipv4_sorted_keys,
45
+ ipv6_map: @ipv6_map,
46
+ ipv6_sorted_keys: @ipv6_sorted_keys,
47
+ }, depth)
48
+ end
49
+
50
+ def self._load(map_str)
51
+ map = Marshal.load(map_str)
52
+ instance.instance_variable_set(:@ipv4_map, map[:ipv4_map])
53
+ instance.instance_variable_set(:@ipv4_sorted_keys, map[:ipv4_sorted_keys])
54
+ instance.instance_variable_set(:@ipv6_map, map[:ipv6_map])
55
+ instance.instance_variable_set(:@ipv6_sorted_keys, map[:ipv6_sorted_keys])
56
+ instance
57
+ end
58
+
59
+ def self.cache!
60
+ File.open(cache_path, "wb+") { |f| f.write Marshal.dump(instance) }
61
+ end
62
+
63
+ def self.load_from_cache
64
+ Marshal.load(File.read(cache_path))
65
+ end
66
+
67
+ def load_csvs
68
+ require 'csv'
69
+ @ipv4_map = {}
70
+ File.open(self.class.ipv4_num_csv_path) do |file|
71
+ CSV.foreach(file, headers: false) do |row|
72
+ from, _, country = row
73
+ @ipv4_map[from.to_i] = country.to_sym
74
+ end
75
+ end
76
+ @ipv4_sorted_keys = @ipv4_map.keys.sort.freeze
77
+
78
+ @ipv6_map = {}
79
+ File.open(self.class.ipv6_num_csv_path) do |file|
80
+ CSV.foreach(file, headers: false) do |row|
81
+ from, _, country = row
82
+ @ipv6_map[from.to_i] = country.to_sym
83
+ end
84
+ end
85
+ @ipv6_sorted_keys = @ipv6_map.keys.sort.freeze
86
+ nil
87
+ end
88
+
89
+ def _lookup(ip)
90
+ ip = IPAddr.new(ip) if ip.is_a?(String)
91
+ ip_i = ip.to_i
92
+ if ip.ipv4?
93
+ @ipv4_map[@ipv4_sorted_keys.bsearch { |x| x >= ip_i }]
94
+ else
95
+ @ipv6_map[@ipv6_sorted_keys.bsearch { |x| x >= ip_i }]
96
+ end
97
+ end
98
+ end
99
+ end
data/sig/benchmark.rbs ADDED
@@ -0,0 +1,15 @@
1
+ class BenchmarkTest
2
+ include GeoipWhoisAsnCountry
3
+
4
+ def lookup: (untyped ip) -> untyped
5
+
6
+ def benchmark_load: () -> untyped
7
+
8
+ def cached_load: () -> untyped
9
+
10
+ def measure: (untyped title) { () -> untyped } -> untyped
11
+
12
+ def test_function: () -> untyped
13
+
14
+ def test_benchmark: () -> untyped
15
+ end
@@ -0,0 +1,39 @@
1
+ # TypeProf 0.21.3
2
+
3
+ # Classes
4
+ module GeoipWhoisAsnCountry
5
+ VERSION: String
6
+
7
+ def self.lookup: (String | IPAddr ip_address) -> Symbol?
8
+ def self.configure: () { ( singleton(GeoIpCountry) ) -> untyped } -> nil
9
+
10
+ class GeoIpCountry
11
+ include Singleton
12
+
13
+ self.@singleton__instance__: untyped
14
+ @ipv4_map: Hash[Integer, Symbol]
15
+ @ipv4_sorted_keys: Array[Integer]
16
+ @ipv6_map: Hash[Integer, Symbol]
17
+ @ipv6_sorted_keys: Array[Integer]
18
+
19
+ def self.cache_path: -> String
20
+ def self.cache_path=: (String path) -> String
21
+
22
+ def self.ipv6_num_csv_path: -> String
23
+ def self.ipv6_num_csv_path=: (String path) -> String
24
+
25
+ def self.ipv4_num_csv_path: -> String
26
+ def self.ipv4_num_csv_path=: (String path) -> String
27
+
28
+ def self.instance: -> GeoIpCountry
29
+
30
+
31
+ def self._lookup: (String | IPAddr ip) -> Symbol?
32
+ def _dump: (untyped depth) -> String
33
+ def self._load: (untyped map_str) -> GeoIpCountry
34
+ def self.cache!: -> Integer
35
+ def self.load_from_cache: -> GeoIpCountry
36
+ def load_csvs: -> nil
37
+ def _lookup: (String | IPAddr ip) -> Symbol?
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoip_whois_asn_country
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Stefan Wienert
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-08-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Efficient lookup of ipv4/ipv6 to country using the node-modules's geo-whois-asn-country
14
+ CSVs.
15
+ email:
16
+ - info@stefanwienert.de
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - Gemfile
22
+ - LICENSE.txt
23
+ - README.md
24
+ - Rakefile
25
+ - Steepfile
26
+ - lib/geoip_whois_asn_country.rb
27
+ - lib/geoip_whois_asn_country/version.rb
28
+ - sig/benchmark.rbs
29
+ - sig/geoip_whois_asn_country.rbs
30
+ homepage: https://github.com/pludoni/ruby-geoip_whois_asn_country
31
+ licenses:
32
+ - MIT
33
+ metadata:
34
+ homepage_uri: https://github.com/pludoni/ruby-geoip_whois_asn_country
35
+ source_code_uri: https://github.com/pludoni/ruby-geoip_whois_asn_country
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.6.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.4.6
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Efficient lookup of ipv4/ipv6 to country using the node-modules's geo-whois-asn-country
55
+ CSVs.
56
+ test_files: []