maxminddb 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +4 -0
- data/README.md +18 -5
- data/lib/maxminddb.rb +7 -1
- data/lib/maxminddb/reader.rb +12 -4
- data/lib/maxminddb/version.rb +1 -1
- data/spec/maxminddb_spec.rb +166 -157
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab8d608c0e8a6e577bdf66c0d2523c33f8d61154
|
4
|
+
data.tar.gz: 7e2ab98277eef7c50c62e8878082ac404aade464
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c002cc49899ffa54ee320eb2c867e7b88d50e343da99a88217b5a7f0251863c1be4c8fc98c70c2038efd6362df78db1b8c2ff7ce77782d3d14fee561d2bdd75
|
7
|
+
data.tar.gz: a4888c65e1bf9bc8381f16c837f3b86cbd12f9dbf62eb840767ece6e8c18b2180cddff71c14b0630a49357635404176bf5dd9417a960c1bb6b01212c48db781d
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -81,10 +81,23 @@ A MaxMindDB instance doesn't do any write operation after it is created. So we c
|
|
81
81
|
|
82
82
|
maxminddb-docker: https://github.com/samnissen/maxminddb-docker
|
83
83
|
|
84
|
+
### File reading strategies
|
85
|
+
|
86
|
+
By default, `MaxMinDB.new` will read the entire database into memory. This makes subsequent lookups fast, but can result in a fairly large memory overhead.
|
87
|
+
|
88
|
+
If having a low memory overhead is important, you can use the `LowMemoryReader` by passing a `file_reader` argument to `MaxMindDB.new`. For example:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
db = MaxMindDB.new('./GeoLite2-City.mmdb', MaxMindDB::LOW_MEMORY_FILE_READER)
|
92
|
+
ret = db.lookup('74.125.225.224')
|
93
|
+
```
|
94
|
+
|
95
|
+
The `LowMemoryReader` will not load the entire database into memory. It's important to note that for Ruby versions lower than `2.5.0`, the `LowMemoryReader` is not process safe. Forking a process after initializing a `MaxMindDB` instance can lead to unexpected results. For Ruby versions >= `2.5.0`, `LowMemoryReader` uses `File.pread` which works safely in forking environments.
|
96
|
+
|
84
97
|
## Contributing
|
85
98
|
|
86
|
-
1.
|
87
|
-
2.
|
88
|
-
3.
|
89
|
-
4.
|
90
|
-
5.
|
99
|
+
1. Fork it ( http://github.com/yhirose/maxminddb/fork )
|
100
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
101
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
102
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
103
|
+
5. Create new Pull Request
|
data/lib/maxminddb.rb
CHANGED
@@ -5,7 +5,13 @@ require 'ipaddr'
|
|
5
5
|
|
6
6
|
module MaxMindDB
|
7
7
|
|
8
|
-
|
8
|
+
# The default reader for MaxMindDB files. Reads the database into memory.
|
9
|
+
# This creates a higher memory overhead, but faster lookup times.
|
10
|
+
DEFAULT_FILE_READER = proc { |path| File.binread(path) }
|
11
|
+
|
12
|
+
# A low memory file reader for MaxMindDB files. Avoids reading the database
|
13
|
+
# into memory. Has a lower memory footprint but slower lookup times.
|
14
|
+
LOW_MEMORY_FILE_READER = proc { |path| MaxMindDB::LowMemoryReader.new(path) }
|
9
15
|
|
10
16
|
def self.new(path, file_reader=DEFAULT_FILE_READER)
|
11
17
|
Client.new(path, file_reader)
|
data/lib/maxminddb/reader.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
|
2
|
+
require 'thread'
|
3
|
+
|
2
4
|
module MaxMindDB
|
3
|
-
class
|
5
|
+
class LowMemoryReader
|
4
6
|
METADATA_MAX_SIZE = 128 * 1024
|
5
7
|
|
6
8
|
def initialize(path)
|
@@ -21,9 +23,15 @@ module MaxMindDB
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def atomic_read(length, pos)
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
# Prefer `pread` in environments where it is available. `pread` provides
|
27
|
+
# atomic file access across processes.
|
28
|
+
if @file.respond_to?(:pread)
|
29
|
+
@file.pread(length, pos)
|
30
|
+
else
|
31
|
+
@mutex.synchronize do
|
32
|
+
@file.seek(pos)
|
33
|
+
@file.read(length)
|
34
|
+
end
|
27
35
|
end
|
28
36
|
end
|
29
37
|
end
|
data/lib/maxminddb/version.rb
CHANGED
data/spec/maxminddb_spec.rb
CHANGED
@@ -1,215 +1,224 @@
|
|
1
1
|
require 'maxminddb'
|
2
2
|
|
3
3
|
describe MaxMindDB do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
[
|
5
|
+
['default file reader', MaxMindDB::DEFAULT_FILE_READER],
|
6
|
+
['low memory file reader', MaxMindDB::LOW_MEMORY_FILE_READER],
|
7
|
+
].each do |file_reader|
|
8
|
+
description, reader = file_reader
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
describe description do
|
11
|
+
let(:city_db) { MaxMindDB.new('spec/cache/GeoLite2-City.mmdb', reader) }
|
12
|
+
let(:country_db) { MaxMindDB.new('spec/cache/GeoLite2-Country.mmdb', reader) }
|
13
|
+
let(:rec32_db) { MaxMindDB.new('spec/data/32bit_record_data.mmdb', reader) }
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
15
|
+
context 'for the ip 74.125.225.224' do
|
16
|
+
let(:ip) { '74.125.225.224' }
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
it 'returns a MaxMindDB::Result' do
|
19
|
+
expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
it 'finds data' do
|
23
|
+
expect(city_db.lookup(ip)).to be_found
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
it 'returns Mountain View as the English name' do
|
27
|
+
expect(city_db.lookup(ip).city.name).to eq('Alameda')
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
it 'returns -122.0574 as the longitude' do
|
31
|
+
expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
|
32
|
+
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
it 'returns nil for is_anonymous_proxy' do
|
35
|
+
expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
|
36
|
+
end
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
it 'returns United States as the English country name' do
|
39
|
+
expect(country_db.lookup(ip).country.name).to eq('United States')
|
40
|
+
end
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
it 'returns false for the is_in_european_union' do
|
43
|
+
expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
it 'returns US as the country iso code' do
|
47
|
+
expect(country_db.lookup(ip).country.iso_code).to eq('US')
|
48
|
+
end
|
45
49
|
|
46
|
-
|
47
|
-
|
48
|
-
end
|
50
|
+
context 'as a Integer' do
|
51
|
+
let(:integer_ip) { IPAddr.new(ip).to_i }
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
+
it 'returns a MaxMindDB::Result' do
|
54
|
+
expect(city_db.lookup(integer_ip)).to be_kind_of(MaxMindDB::Result)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns Mountain View as the English name' do
|
58
|
+
expect(city_db.lookup(integer_ip).city.name).to eq('Alameda')
|
59
|
+
end
|
53
60
|
|
54
|
-
|
55
|
-
|
61
|
+
it 'returns United States as the English country name' do
|
62
|
+
expect(country_db.lookup(integer_ip).country.name).to eq('United States')
|
63
|
+
end
|
64
|
+
end
|
56
65
|
end
|
57
|
-
end
|
58
|
-
end
|
59
66
|
|
60
|
-
|
61
|
-
|
67
|
+
context 'for the ip 2001:708:510:8:9a6:442c:f8e0:7133' do
|
68
|
+
let(:ip) { '2001:708:510:8:9a6:442c:f8e0:7133' }
|
62
69
|
|
63
|
-
|
64
|
-
|
65
|
-
|
70
|
+
it 'finds data' do
|
71
|
+
expect(city_db.lookup(ip)).to be_found
|
72
|
+
end
|
66
73
|
|
67
|
-
|
68
|
-
|
69
|
-
|
74
|
+
it 'returns true for the is_in_european_union' do
|
75
|
+
expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
|
76
|
+
end
|
70
77
|
|
71
|
-
|
72
|
-
|
73
|
-
|
78
|
+
it 'returns FI as the country iso code' do
|
79
|
+
expect(country_db.lookup(ip).country.iso_code).to eq('FI')
|
80
|
+
end
|
74
81
|
|
75
|
-
|
76
|
-
|
82
|
+
context 'as an integer' do
|
83
|
+
let(:integer_ip) { IPAddr.new(ip).to_i }
|
77
84
|
|
78
|
-
|
79
|
-
|
85
|
+
it 'returns FI as the country iso code' do
|
86
|
+
expect(country_db.lookup(integer_ip).country.iso_code).to eq('FI')
|
87
|
+
end
|
88
|
+
end
|
80
89
|
end
|
81
|
-
end
|
82
|
-
end
|
83
90
|
|
84
|
-
|
85
|
-
|
91
|
+
context 'for a Canadian ipv6' do
|
92
|
+
let(:ip) { '2607:5300:60:72ba::' }
|
86
93
|
|
87
|
-
|
88
|
-
|
89
|
-
|
94
|
+
it 'finds data' do
|
95
|
+
expect(city_db.lookup(ip)).to be_found
|
96
|
+
end
|
90
97
|
|
91
|
-
|
92
|
-
|
93
|
-
|
98
|
+
it 'returns true for the is_in_european_union' do
|
99
|
+
expect(country_db.lookup(ip).country.is_in_european_union).to be_falsey
|
100
|
+
end
|
94
101
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
102
|
+
it 'returns CA as the country iso code' do
|
103
|
+
expect(country_db.lookup(ip).country.iso_code).to eq('CA')
|
104
|
+
end
|
105
|
+
end
|
99
106
|
|
100
|
-
|
101
|
-
|
107
|
+
context 'for a German IPv6' do
|
108
|
+
let(:ip) { '2a01:488:66:1000:2ea3:495e::1' }
|
102
109
|
|
103
|
-
|
104
|
-
|
105
|
-
|
110
|
+
it 'finds data' do
|
111
|
+
expect(city_db.lookup(ip)).to be_found
|
112
|
+
end
|
106
113
|
|
107
|
-
|
108
|
-
|
109
|
-
|
114
|
+
it 'returns true for the is_in_european_union' do
|
115
|
+
expect(country_db.lookup(ip).country.is_in_european_union).to eq(true)
|
116
|
+
end
|
110
117
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
118
|
+
it 'returns DE as the country iso code' do
|
119
|
+
expect(country_db.lookup(ip).country.iso_code).to eq('DE')
|
120
|
+
end
|
121
|
+
end
|
115
122
|
|
116
|
-
|
117
|
-
|
123
|
+
context 'for the ip 127.0.0.1' do
|
124
|
+
let(:ip) { '127.0.0.1' }
|
118
125
|
|
119
|
-
|
120
|
-
|
121
|
-
|
126
|
+
it 'returns a MaxMindDB::Result' do
|
127
|
+
expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
|
128
|
+
end
|
122
129
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
130
|
+
it "doesn't find data" do
|
131
|
+
expect(city_db.lookup(ip)).to_not be_found
|
132
|
+
end
|
133
|
+
end
|
127
134
|
|
128
|
-
|
129
|
-
|
135
|
+
context 'for local ip addresses' do
|
136
|
+
let(:ip) { '127.0.0.1' }
|
130
137
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
138
|
+
context 'for city_db' do
|
139
|
+
before do
|
140
|
+
city_db.local_ip_alias = '74.125.225.224'
|
141
|
+
end
|
135
142
|
|
136
|
-
|
137
|
-
|
138
|
-
|
143
|
+
it 'returns a MaxMindDB::Result' do
|
144
|
+
expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
|
145
|
+
end
|
139
146
|
|
140
|
-
|
141
|
-
|
142
|
-
|
147
|
+
it 'finds data' do
|
148
|
+
expect(city_db.lookup(ip)).to be_found
|
149
|
+
end
|
143
150
|
|
144
|
-
|
145
|
-
|
146
|
-
|
151
|
+
it 'returns Mountain View as the English name' do
|
152
|
+
expect(city_db.lookup(ip).city.name).to eq('Alameda')
|
153
|
+
end
|
147
154
|
|
148
|
-
|
149
|
-
|
150
|
-
|
155
|
+
it 'returns -122.0574 as the longitude' do
|
156
|
+
expect(city_db.lookup(ip).location.longitude).to eq(-122.2788)
|
157
|
+
end
|
151
158
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
159
|
+
it 'returns nil for is_anonymous_proxy' do
|
160
|
+
expect(city_db.lookup(ip).traits.is_anonymous_proxy).to eq(nil)
|
161
|
+
end
|
162
|
+
end
|
156
163
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
164
|
+
context 'for country_db' do
|
165
|
+
before do
|
166
|
+
country_db.local_ip_alias = '74.125.225.224'
|
167
|
+
end
|
161
168
|
|
162
|
-
|
163
|
-
|
164
|
-
|
169
|
+
it 'returns United States as the English country name' do
|
170
|
+
expect(country_db.lookup(ip).country.name).to eq('United States')
|
171
|
+
end
|
165
172
|
|
166
|
-
|
167
|
-
|
168
|
-
|
173
|
+
it 'returns false for the is_in_european_union' do
|
174
|
+
expect(country_db.lookup(ip).country.is_in_european_union).to eq(nil)
|
175
|
+
end
|
169
176
|
|
170
|
-
|
171
|
-
|
177
|
+
it 'returns US as the country iso code' do
|
178
|
+
expect(country_db.lookup(ip).country.iso_code).to eq('US')
|
179
|
+
end
|
180
|
+
end
|
172
181
|
end
|
173
|
-
end
|
174
|
-
end
|
175
182
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
it 'finds data' do
|
180
|
-
expect(rec32_db.lookup(ip)).to be_found
|
181
|
-
end
|
182
|
-
end
|
183
|
+
context 'for 32bit record data' do
|
184
|
+
let(:ip) { '1.0.16.1' }
|
183
185
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
['178.72.254.1', 'CZ'],
|
188
|
-
['95.153.177.210', 'RU'],
|
189
|
-
['200.148.105.119', 'BR'],
|
190
|
-
['195.59.71.43', 'GB'],
|
191
|
-
['179.175.47.87', 'BR'],
|
192
|
-
['202.67.40.50', 'ID'],
|
193
|
-
].each do |ip, iso|
|
194
|
-
it 'returns a MaxMindDB::Result' do
|
195
|
-
expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
|
186
|
+
it 'finds data' do
|
187
|
+
expect(rec32_db.lookup(ip)).to be_found
|
188
|
+
end
|
196
189
|
end
|
197
190
|
|
198
|
-
|
199
|
-
|
191
|
+
context 'test ips' do
|
192
|
+
[
|
193
|
+
['185.23.124.1', 'SA'],
|
194
|
+
['178.72.254.1', 'CZ'],
|
195
|
+
['95.153.177.210', 'RU'],
|
196
|
+
['200.148.105.119', 'BR'],
|
197
|
+
['195.59.71.43', 'GB'],
|
198
|
+
['179.175.47.87', 'BR'],
|
199
|
+
['202.67.40.50', 'ID'],
|
200
|
+
].each do |ip, iso|
|
201
|
+
it 'returns a MaxMindDB::Result' do
|
202
|
+
expect(city_db.lookup(ip)).to be_kind_of(MaxMindDB::Result)
|
203
|
+
end
|
204
|
+
|
205
|
+
it "returns #{iso} as the country iso code" do
|
206
|
+
expect(country_db.lookup(ip).country.iso_code).to eq(iso)
|
207
|
+
end
|
208
|
+
end
|
200
209
|
end
|
201
|
-
end
|
202
|
-
end
|
203
210
|
|
204
|
-
|
205
|
-
|
211
|
+
context 'test boolean data' do
|
212
|
+
let(:ip) { '41.194.0.1' }
|
206
213
|
|
207
|
-
|
208
|
-
|
209
|
-
|
214
|
+
it 'returns true for the is_satellite_provider trait' do
|
215
|
+
expect(city_db.lookup(ip).traits.is_satellite_provider).to eq(nil)
|
216
|
+
end
|
210
217
|
|
211
|
-
|
212
|
-
|
218
|
+
# There are no false booleans in the database that we can test.
|
219
|
+
# False values are simply omitted.
|
220
|
+
end
|
221
|
+
end
|
213
222
|
end
|
214
223
|
end
|
215
224
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maxminddb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yhirose
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|