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 +7 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +59 -0
- data/Rakefile +4 -0
- data/Steepfile +14 -0
- data/lib/geoip_whois_asn_country/version.rb +5 -0
- data/lib/geoip_whois_asn_country.rb +99 -0
- data/sig/benchmark.rbs +15 -0
- data/sig/geoip_whois_asn_country.rbs +39 -0
- metadata +56 -0
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
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
data/Steepfile
ADDED
@@ -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: []
|