maxmind-geoip2 0.1.0 → 0.6.0
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/CHANGELOG.md +32 -0
- data/Gemfile +1 -5
- data/README.dev.md +1 -1
- data/README.md +82 -8
- data/lib/maxmind/geoip2.rb +1 -0
- data/lib/maxmind/geoip2/client.rb +333 -0
- data/lib/maxmind/geoip2/errors.rb +37 -3
- data/lib/maxmind/geoip2/model/abstract.rb +19 -15
- data/lib/maxmind/geoip2/model/anonymous_ip.rb +62 -50
- data/lib/maxmind/geoip2/model/asn.rb +33 -29
- data/lib/maxmind/geoip2/model/city.rb +59 -55
- data/lib/maxmind/geoip2/model/connection_type.rb +27 -23
- data/lib/maxmind/geoip2/model/country.rb +64 -53
- data/lib/maxmind/geoip2/model/domain.rb +27 -23
- data/lib/maxmind/geoip2/model/enterprise.rb +13 -9
- data/lib/maxmind/geoip2/model/insights.rb +18 -0
- data/lib/maxmind/geoip2/model/isp.rb +45 -41
- data/lib/maxmind/geoip2/reader.rb +260 -233
- data/lib/maxmind/geoip2/record/abstract.rb +17 -13
- data/lib/maxmind/geoip2/record/city.rb +33 -29
- data/lib/maxmind/geoip2/record/continent.rb +32 -28
- data/lib/maxmind/geoip2/record/country.rb +47 -43
- data/lib/maxmind/geoip2/record/location.rb +64 -60
- data/lib/maxmind/geoip2/record/maxmind.rb +21 -0
- data/lib/maxmind/geoip2/record/place.rb +22 -18
- data/lib/maxmind/geoip2/record/postal.rb +26 -22
- data/lib/maxmind/geoip2/record/represented_country.rb +20 -16
- data/lib/maxmind/geoip2/record/subdivision.rb +42 -38
- data/lib/maxmind/geoip2/record/traits.rb +204 -191
- data/maxmind-geoip2.gemspec +11 -3
- data/test/data/bad-data/maxminddb-python/bad-unicode-in-map-key.mmdb +0 -0
- data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +1 -0
- data/test/data/source-data/GeoIP2-ISP-Test.json +3 -1
- data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +87 -0
- data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
- data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
- data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
- data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
- data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
- data/test/data/test-data/write-test-data.pl +68 -18
- data/test/test_client.rb +426 -0
- data/test/test_model_country.rb +16 -0
- data/test/test_reader.rb +59 -0
- metadata +113 -10
- data/Gemfile.lock +0 -38
data/maxmind-geoip2.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.files = Dir['**/*']
|
6
6
|
s.name = 'maxmind-geoip2'
|
7
7
|
s.summary = 'A gem for interacting with the GeoIP2 webservices and databases.'
|
8
|
-
s.version = '0.
|
8
|
+
s.version = '0.6.0'
|
9
9
|
|
10
10
|
s.description = 'A gem for interacting with the GeoIP2 webservices and databases. MaxMind provides geolocation data as downloadable databases as well as through a webservice.'
|
11
11
|
s.email = 'support@maxmind.com'
|
@@ -13,12 +13,20 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.licenses = ['Apache-2.0', 'MIT']
|
14
14
|
s.metadata = {
|
15
15
|
'bug_tracker_uri' => 'https://github.com/maxmind/GeoIP2-ruby/issues',
|
16
|
-
'changelog_uri' => 'https://github.com/maxmind/GeoIP2-ruby/blob/
|
17
|
-
'documentation_uri' => 'https://
|
16
|
+
'changelog_uri' => 'https://github.com/maxmind/GeoIP2-ruby/blob/main/CHANGELOG.md',
|
17
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/maxmind-geoip2',
|
18
18
|
'homepage_uri' => 'https://github.com/maxmind/GeoIP2-ruby',
|
19
19
|
'source_code_uri' => 'https://github.com/maxmind/GeoIP2-ruby',
|
20
20
|
}
|
21
21
|
s.required_ruby_version = '>= 2.4.0'
|
22
22
|
|
23
|
+
s.add_runtime_dependency 'connection_pool', ['~> 2.2']
|
24
|
+
s.add_runtime_dependency 'http', ['~> 4.3']
|
23
25
|
s.add_runtime_dependency 'maxmind-db', ['~> 1.1']
|
26
|
+
|
27
|
+
s.add_development_dependency 'minitest'
|
28
|
+
s.add_development_dependency 'rake'
|
29
|
+
s.add_development_dependency 'rubocop'
|
30
|
+
s.add_development_dependency 'rubocop-performance'
|
31
|
+
s.add_development_dependency 'webmock'
|
24
32
|
end
|
Binary file
|
@@ -12587,7 +12587,9 @@
|
|
12587
12587
|
{
|
12588
12588
|
"2c0f:ff80::/25" : {
|
12589
12589
|
"autonomous_system_number" : 237,
|
12590
|
-
"autonomous_system_organization" : "Merit Network Inc."
|
12590
|
+
"autonomous_system_organization" : "Merit Network Inc.",
|
12591
|
+
"isp" : "Merit Network Inc.",
|
12592
|
+
"organization" : "Merit Network Inc."
|
12591
12593
|
}
|
12592
12594
|
}
|
12593
12595
|
]
|
@@ -2057,5 +2057,92 @@
|
|
2057
2057
|
"user_type" : "government"
|
2058
2058
|
}
|
2059
2059
|
}
|
2060
|
+
},
|
2061
|
+
{
|
2062
|
+
"::2.20.32.110/127" : {
|
2063
|
+
"city" : {
|
2064
|
+
"confidence" : 60,
|
2065
|
+
"geoname_id" : 315808,
|
2066
|
+
"names" : {
|
2067
|
+
"de" : "Elazığ",
|
2068
|
+
"en" : "Elâzığ",
|
2069
|
+
"fr" : "Elazığ",
|
2070
|
+
"ja" : "エラズー",
|
2071
|
+
"ru" : "Элязыг",
|
2072
|
+
"zh-CN" : "埃拉泽"
|
2073
|
+
}
|
2074
|
+
},
|
2075
|
+
"continent" : {
|
2076
|
+
"code" : "AS",
|
2077
|
+
"geoname_id" : 6255147,
|
2078
|
+
"names" : {
|
2079
|
+
"de" : "Asien",
|
2080
|
+
"en" : "Asia",
|
2081
|
+
"es" : "Asia",
|
2082
|
+
"fr" : "Asie",
|
2083
|
+
"ja" : "アジア",
|
2084
|
+
"pt-BR" : "Ásia",
|
2085
|
+
"ru" : "Азия",
|
2086
|
+
"zh-CN" : "亚洲"
|
2087
|
+
}
|
2088
|
+
},
|
2089
|
+
"country" : {
|
2090
|
+
"confidence" : 90,
|
2091
|
+
"geoname_id" : 298795,
|
2092
|
+
"iso_code" : "TR",
|
2093
|
+
"names" : {
|
2094
|
+
"de" : "Türkei",
|
2095
|
+
"en" : "Turkey",
|
2096
|
+
"es" : "Turquía",
|
2097
|
+
"fr" : "Turquie",
|
2098
|
+
"ja" : "トルコ共和国",
|
2099
|
+
"pt-BR" : "Turquia",
|
2100
|
+
"ru" : "Турция",
|
2101
|
+
"zh-CN" : "土耳其"
|
2102
|
+
}
|
2103
|
+
},
|
2104
|
+
"location" : {
|
2105
|
+
"accuracy_radius" : 50,
|
2106
|
+
"latitude" : 38.6229,
|
2107
|
+
"longitude" : 39.3217,
|
2108
|
+
"time_zone" : "Europe/Istanbul"
|
2109
|
+
},
|
2110
|
+
"postal" : {
|
2111
|
+
"code" : "23100",
|
2112
|
+
"confidence" : 30
|
2113
|
+
},
|
2114
|
+
"registered_country" : {
|
2115
|
+
"geoname_id" : 298795,
|
2116
|
+
"iso_code" : "TR",
|
2117
|
+
"names" : {
|
2118
|
+
"de" : "Türkei",
|
2119
|
+
"en" : "Turkey",
|
2120
|
+
"es" : "Turquía",
|
2121
|
+
"fr" : "Turquie",
|
2122
|
+
"ja" : "トルコ共和国",
|
2123
|
+
"pt-BR" : "Turquia",
|
2124
|
+
"ru" : "Турция",
|
2125
|
+
"zh-CN" : "土耳其"
|
2126
|
+
}
|
2127
|
+
},
|
2128
|
+
"subdivisions" : [
|
2129
|
+
{
|
2130
|
+
"confidence" : 60,
|
2131
|
+
"geoname_id" : 315807,
|
2132
|
+
"iso_code" : "23",
|
2133
|
+
"names" : {
|
2134
|
+
"en" : "Elazığ"
|
2135
|
+
}
|
2136
|
+
}
|
2137
|
+
],
|
2138
|
+
"traits" : {
|
2139
|
+
"autonomous_system_number" : 8517,
|
2140
|
+
"autonomous_system_organization" : "National Academic Network and Information Center",
|
2141
|
+
"connection_type" : "Cable/DSL",
|
2142
|
+
"isp" : "National Academic Network and Information Center",
|
2143
|
+
"organization" : "National Academic Network and Information Center",
|
2144
|
+
"user_type" : "business"
|
2145
|
+
}
|
2146
|
+
}
|
2060
2147
|
}
|
2061
2148
|
]
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -19,7 +19,7 @@ use Test::MaxMind::DB::Common::Util qw( standard_test_metadata );
|
|
19
19
|
my $Dir = dirname( abs_path($0) );
|
20
20
|
|
21
21
|
sub main {
|
22
|
-
my @sizes
|
22
|
+
my @sizes = ( 24, 28, 32 );
|
23
23
|
my @ipv4_range = ( '1.1.1.1', '1.1.1.32' );
|
24
24
|
|
25
25
|
my @ipv4_subnets = Net::Works::Network->range_as_subnets(@ipv4_range);
|
@@ -71,6 +71,7 @@ sub main {
|
|
71
71
|
}
|
72
72
|
|
73
73
|
write_decoder_test_db();
|
74
|
+
write_pointer_decoder_test_db();
|
74
75
|
write_deeply_nested_structures_db();
|
75
76
|
|
76
77
|
write_geoip2_dbs();
|
@@ -231,23 +232,7 @@ sub write_test_db {
|
|
231
232
|
);
|
232
233
|
|
233
234
|
sub write_decoder_test_db {
|
234
|
-
my $writer =
|
235
|
-
ip_version => 6,
|
236
|
-
record_size => 24,
|
237
|
-
database_type => 'MaxMind DB Decoder Test',
|
238
|
-
languages => ['en'],
|
239
|
-
description => {
|
240
|
-
en =>
|
241
|
-
'MaxMind DB Decoder Test database - contains every MaxMind DB data type',
|
242
|
-
},
|
243
|
-
alias_ipv6_to_ipv4 => 1,
|
244
|
-
remove_reserved_networks => 0,
|
245
|
-
map_key_type_callback => sub {
|
246
|
-
my $key = $_[0];
|
247
|
-
$key =~ s/X$//;
|
248
|
-
return $key eq 'array' ? [ 'array', 'uint32' ] : $key;
|
249
|
-
},
|
250
|
-
);
|
235
|
+
my $writer = _decoder_writer();
|
251
236
|
|
252
237
|
my @subnets
|
253
238
|
= map { Net::Works::Network->new_from_string( string => $_ ) }
|
@@ -285,6 +270,70 @@ sub write_test_db {
|
|
285
270
|
|
286
271
|
return;
|
287
272
|
}
|
273
|
+
|
274
|
+
sub write_pointer_decoder_test_db {
|
275
|
+
|
276
|
+
# We want to create a database where most values are pointers
|
277
|
+
no warnings 'redefine';
|
278
|
+
local *MaxMind::DB::Writer::Serializer::_should_cache_value
|
279
|
+
= sub { 1 };
|
280
|
+
my $writer = _decoder_writer();
|
281
|
+
|
282
|
+
# We add these slightly different records so that we end up with
|
283
|
+
# pointers for the individual values in the maps, not just pointers
|
284
|
+
# to the map
|
285
|
+
$writer->insert_network(
|
286
|
+
'1.0.0.0/32',
|
287
|
+
{
|
288
|
+
%all_types,
|
289
|
+
booleanX => 0,
|
290
|
+
arrayX => [ 1, 2, 3, 4, ],
|
291
|
+
mapXX => {
|
292
|
+
utf8_stringX => 'hello',
|
293
|
+
arrayX => [ 7, 8, 9, 10 ],
|
294
|
+
booleanX => 0,
|
295
|
+
},
|
296
|
+
},
|
297
|
+
);
|
298
|
+
|
299
|
+
$writer->insert_network(
|
300
|
+
'1.1.1.0/32',
|
301
|
+
{
|
302
|
+
%all_types,
|
303
|
+
|
304
|
+
# This has to be 0 rather than 1 as otherwise the buggy
|
305
|
+
# Perl writer will think it is the same as an uint32 value of
|
306
|
+
# 1 and make a pointer to a value of a different type.
|
307
|
+
boolean => 0,
|
308
|
+
},
|
309
|
+
);
|
310
|
+
|
311
|
+
open my $fh, '>', "$Dir/MaxMind-DB-test-pointer-decoder.mmdb";
|
312
|
+
$writer->write_tree($fh);
|
313
|
+
close $fh;
|
314
|
+
|
315
|
+
return;
|
316
|
+
}
|
317
|
+
|
318
|
+
sub _decoder_writer {
|
319
|
+
return MaxMind::DB::Writer::Tree->new(
|
320
|
+
ip_version => 6,
|
321
|
+
record_size => 24,
|
322
|
+
database_type => 'MaxMind DB Decoder Test',
|
323
|
+
languages => ['en'],
|
324
|
+
description => {
|
325
|
+
en =>
|
326
|
+
'MaxMind DB Decoder Test database - contains every MaxMind DB data type',
|
327
|
+
},
|
328
|
+
alias_ipv6_to_ipv4 => 1,
|
329
|
+
remove_reserved_networks => 0,
|
330
|
+
map_key_type_callback => sub {
|
331
|
+
my $key = $_[0];
|
332
|
+
$key =~ s/X*$//;
|
333
|
+
return $key eq 'array' ? [ 'array', 'uint32' ] : $key;
|
334
|
+
},
|
335
|
+
);
|
336
|
+
}
|
288
337
|
}
|
289
338
|
|
290
339
|
{
|
@@ -427,6 +476,7 @@ sub _universal_map_key_type_callback {
|
|
427
476
|
is_in_european_union => 'boolean',
|
428
477
|
is_legitimate_proxy => 'boolean',
|
429
478
|
is_public_proxy => 'boolean',
|
479
|
+
is_residential_proxy => 'boolean',
|
430
480
|
is_satellite_provider => 'boolean',
|
431
481
|
is_tor_exit_node => 'boolean',
|
432
482
|
iso_code => 'utf8_string',
|
data/test/test_client.rb
ADDED
@@ -0,0 +1,426 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'maxmind/geoip2'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require 'webmock/minitest'
|
7
|
+
|
8
|
+
class ClientTest < Minitest::Test
|
9
|
+
COUNTRY = {
|
10
|
+
'continent' => {
|
11
|
+
'code' => 'NA',
|
12
|
+
'geoname_id' => 42,
|
13
|
+
'names' => { 'en' => 'North America' },
|
14
|
+
},
|
15
|
+
'country' => {
|
16
|
+
'geoname_id' => 1,
|
17
|
+
'iso_code' => 'US',
|
18
|
+
'names' => { 'en' => 'United States of America' },
|
19
|
+
},
|
20
|
+
'maxmind' => {
|
21
|
+
'queries_remaining' => 11,
|
22
|
+
},
|
23
|
+
'traits' => {
|
24
|
+
'ip_address' => '1.2.3.4',
|
25
|
+
'network' => '1.2.3.0/24',
|
26
|
+
},
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
INSIGHTS = {
|
30
|
+
'continent' => {
|
31
|
+
'code' => 'NA',
|
32
|
+
'geoname_id' => 42,
|
33
|
+
'names' => { 'en' => 'North America' },
|
34
|
+
},
|
35
|
+
'country' => {
|
36
|
+
'geoname_id' => 1,
|
37
|
+
'iso_code' => 'US',
|
38
|
+
'names' => { 'en' => 'United States of America' },
|
39
|
+
},
|
40
|
+
'maxmind' => {
|
41
|
+
'queries_remaining' => 11,
|
42
|
+
},
|
43
|
+
'traits' => {
|
44
|
+
'ip_address' => '1.2.3.40',
|
45
|
+
'is_residential_proxy' => true,
|
46
|
+
'network' => '1.2.3.0/24',
|
47
|
+
'static_ip_score' => 1.3,
|
48
|
+
'user_count' => 2,
|
49
|
+
},
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
CONTENT_TYPES = {
|
53
|
+
country: 'application/vnd.maxmind.com-country+json; charset=UTF-8; version=2.1',
|
54
|
+
}.freeze
|
55
|
+
|
56
|
+
def test_country
|
57
|
+
record = request(:country, '1.2.3.4')
|
58
|
+
|
59
|
+
assert_instance_of(MaxMind::GeoIP2::Model::Country, record)
|
60
|
+
|
61
|
+
assert_equal(42, record.continent.geoname_id)
|
62
|
+
assert_equal('NA', record.continent.code)
|
63
|
+
assert_equal({ 'en' => 'North America' }, record.continent.names)
|
64
|
+
assert_equal('North America', record.continent.name)
|
65
|
+
|
66
|
+
assert_equal(1, record.country.geoname_id)
|
67
|
+
assert_equal(false, record.country.in_european_union?)
|
68
|
+
assert_equal('US', record.country.iso_code)
|
69
|
+
assert_equal({ 'en' => 'United States of America' }, record.country.names)
|
70
|
+
assert_equal('United States of America', record.country.name)
|
71
|
+
|
72
|
+
assert_equal(11, record.maxmind.queries_remaining)
|
73
|
+
|
74
|
+
assert_equal(false, record.registered_country.in_european_union?)
|
75
|
+
|
76
|
+
assert_equal('1.2.3.0/24', record.traits.network)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_insights
|
80
|
+
record = request(:insights, '1.2.3.40')
|
81
|
+
|
82
|
+
assert_instance_of(MaxMind::GeoIP2::Model::Insights, record)
|
83
|
+
|
84
|
+
assert_equal(42, record.continent.geoname_id)
|
85
|
+
|
86
|
+
assert_equal(true, record.traits.residential_proxy?)
|
87
|
+
assert_equal('1.2.3.0/24', record.traits.network)
|
88
|
+
assert_equal(1.3, record.traits.static_ip_score)
|
89
|
+
assert_equal(2, record.traits.user_count)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_city
|
93
|
+
record = request(:city, '1.2.3.4')
|
94
|
+
|
95
|
+
assert_instance_of(MaxMind::GeoIP2::Model::City, record)
|
96
|
+
|
97
|
+
assert_equal('1.2.3.0/24', record.traits.network)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_me
|
101
|
+
record = request(:city, 'me')
|
102
|
+
|
103
|
+
assert_instance_of(MaxMind::GeoIP2::Model::City, record)
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_no_body_error
|
107
|
+
assert_raises(
|
108
|
+
JSON::ParserError,
|
109
|
+
) { request(:country, '1.2.3.5') }
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_bad_body_error
|
113
|
+
assert_raises(
|
114
|
+
JSON::ParserError,
|
115
|
+
) { request(:country, '2.2.3.5') }
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_non_json_success_response
|
119
|
+
error = assert_raises(
|
120
|
+
MaxMind::GeoIP2::HTTPError,
|
121
|
+
) { request(:country, '3.2.3.5') }
|
122
|
+
|
123
|
+
assert_equal(
|
124
|
+
'Received a success response for country but it is not JSON: extra bad body',
|
125
|
+
error.message,
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_invalid_ip_error
|
130
|
+
error = assert_raises(
|
131
|
+
MaxMind::GeoIP2::AddressInvalidError,
|
132
|
+
) { request(:country, '1.2.3.6') }
|
133
|
+
|
134
|
+
assert_equal(
|
135
|
+
'The value "1.2.3" is not a valid IP address',
|
136
|
+
error.message,
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_no_error_body_ip_error
|
141
|
+
assert_raises(
|
142
|
+
JSON::ParserError,
|
143
|
+
) { request(:country, '1.2.3.7') }
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_missing_key_ip_error
|
147
|
+
error = assert_raises(
|
148
|
+
MaxMind::GeoIP2::HTTPError,
|
149
|
+
) { request(:country, '1.2.3.71') }
|
150
|
+
|
151
|
+
assert_equal(
|
152
|
+
'Received client error response (400) that is JSON but does not specify code or error keys: {"code":"HI"}',
|
153
|
+
error.message,
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_weird_error_body_ip_error
|
158
|
+
error = assert_raises(
|
159
|
+
MaxMind::GeoIP2::HTTPError,
|
160
|
+
) { request(:country, '1.2.3.8') }
|
161
|
+
|
162
|
+
assert_equal(
|
163
|
+
'Received client error response (400) that is JSON but does not specify code or error keys: {"weird":42}',
|
164
|
+
error.message,
|
165
|
+
)
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_500_error
|
169
|
+
error = assert_raises(
|
170
|
+
MaxMind::GeoIP2::HTTPError,
|
171
|
+
) { request(:country, '1.2.3.10') }
|
172
|
+
|
173
|
+
assert_equal(
|
174
|
+
'Received server error response (500) for country with body foo',
|
175
|
+
error.message,
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_300_response
|
180
|
+
error = assert_raises(
|
181
|
+
MaxMind::GeoIP2::HTTPError,
|
182
|
+
) { request(:country, '1.2.3.11') }
|
183
|
+
|
184
|
+
assert_equal(
|
185
|
+
'Received unexpected response (300) for country with body bar',
|
186
|
+
error.message,
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_406_error
|
191
|
+
error = assert_raises(
|
192
|
+
MaxMind::GeoIP2::HTTPError,
|
193
|
+
) { request(:country, '1.2.3.12') }
|
194
|
+
|
195
|
+
assert_equal(
|
196
|
+
'Received client error response (406) for country but it is not JSON: Cannot satisfy your Accept-Charset requirements',
|
197
|
+
error.message,
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_address_not_found_error
|
202
|
+
error = assert_raises(
|
203
|
+
MaxMind::GeoIP2::AddressNotFoundError,
|
204
|
+
) { request(:country, '1.2.3.13') }
|
205
|
+
|
206
|
+
assert_equal(
|
207
|
+
'The address "1.2.3.13" is not in our database.',
|
208
|
+
error.message,
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_address_reserved_error
|
213
|
+
error = assert_raises(
|
214
|
+
MaxMind::GeoIP2::AddressReservedError,
|
215
|
+
) { request(:country, '1.2.3.14') }
|
216
|
+
|
217
|
+
assert_equal(
|
218
|
+
'The address "1.2.3.14" is a private address.',
|
219
|
+
error.message,
|
220
|
+
)
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_authorization_error
|
224
|
+
error = assert_raises(
|
225
|
+
MaxMind::GeoIP2::AuthenticationError,
|
226
|
+
) { request(:country, '1.2.3.15') }
|
227
|
+
|
228
|
+
assert_equal(
|
229
|
+
'An account ID and license key are required to use this service.',
|
230
|
+
error.message,
|
231
|
+
)
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_missing_license_key_error
|
235
|
+
error = assert_raises(
|
236
|
+
MaxMind::GeoIP2::AuthenticationError,
|
237
|
+
) { request(:country, '1.2.3.16') }
|
238
|
+
|
239
|
+
assert_equal(
|
240
|
+
'A license key is required to use this service.',
|
241
|
+
error.message,
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_missing_account_id_error
|
246
|
+
error = assert_raises(
|
247
|
+
MaxMind::GeoIP2::AuthenticationError,
|
248
|
+
) { request(:country, '1.2.3.17') }
|
249
|
+
|
250
|
+
assert_equal(
|
251
|
+
'An account ID is required to use this service.',
|
252
|
+
error.message,
|
253
|
+
)
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_insufficient_funds_error
|
257
|
+
error = assert_raises(
|
258
|
+
MaxMind::GeoIP2::InsufficientFundsError,
|
259
|
+
) { request(:country, '1.2.3.18') }
|
260
|
+
|
261
|
+
assert_equal(
|
262
|
+
'The license key you have provided is out of queries.',
|
263
|
+
error.message,
|
264
|
+
)
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_unexpected_code_error
|
268
|
+
error = assert_raises(
|
269
|
+
MaxMind::GeoIP2::InvalidRequestError,
|
270
|
+
) { request(:country, '1.2.3.19') }
|
271
|
+
|
272
|
+
assert_equal(
|
273
|
+
'Whoa!',
|
274
|
+
error.message,
|
275
|
+
)
|
276
|
+
end
|
277
|
+
|
278
|
+
def request(method, ip_address)
|
279
|
+
response = get_response(ip_address)
|
280
|
+
|
281
|
+
stub_request(:get, /geoip/)
|
282
|
+
.to_return(
|
283
|
+
body: response[:body],
|
284
|
+
headers: response[:headers],
|
285
|
+
status: response[:status],
|
286
|
+
)
|
287
|
+
|
288
|
+
client = MaxMind::GeoIP2::Client.new(
|
289
|
+
account_id: 42,
|
290
|
+
license_key: 'abcdef123456',
|
291
|
+
)
|
292
|
+
|
293
|
+
client.send(method, '1.2.3.4')
|
294
|
+
end
|
295
|
+
|
296
|
+
def get_response(ip_address)
|
297
|
+
responses = {
|
298
|
+
'me' => {
|
299
|
+
body: JSON.generate(COUNTRY),
|
300
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
301
|
+
status: 200,
|
302
|
+
},
|
303
|
+
'1.2.3.4' => {
|
304
|
+
body: JSON.generate(COUNTRY),
|
305
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
306
|
+
status: 200,
|
307
|
+
},
|
308
|
+
'1.2.3.5' => {
|
309
|
+
body: '',
|
310
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
311
|
+
status: 200,
|
312
|
+
},
|
313
|
+
'2.2.3.5' => {
|
314
|
+
body: 'bad body',
|
315
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
316
|
+
status: 200,
|
317
|
+
},
|
318
|
+
'3.2.3.5' => {
|
319
|
+
body: 'extra bad body',
|
320
|
+
headers: {},
|
321
|
+
status: 200,
|
322
|
+
},
|
323
|
+
'1.2.3.40' => {
|
324
|
+
body: JSON.generate(INSIGHTS),
|
325
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
326
|
+
status: 200,
|
327
|
+
},
|
328
|
+
'1.2.3.6' => {
|
329
|
+
body: JSON.generate({
|
330
|
+
'code' => 'IP_ADDRESS_INVALID',
|
331
|
+
'error' => 'The value "1.2.3" is not a valid IP address',
|
332
|
+
}),
|
333
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
334
|
+
status: 400,
|
335
|
+
},
|
336
|
+
'1.2.3.7' => {
|
337
|
+
body: '',
|
338
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
339
|
+
status: 400,
|
340
|
+
},
|
341
|
+
'1.2.3.71' => {
|
342
|
+
body: JSON.generate({ code: 'HI' }),
|
343
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
344
|
+
status: 400,
|
345
|
+
},
|
346
|
+
'1.2.3.8' => {
|
347
|
+
body: JSON.generate({ weird: 42 }),
|
348
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
349
|
+
status: 400,
|
350
|
+
},
|
351
|
+
'1.2.3.10' => {
|
352
|
+
body: 'foo',
|
353
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
354
|
+
status: 500,
|
355
|
+
},
|
356
|
+
'1.2.3.11' => {
|
357
|
+
body: 'bar',
|
358
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
359
|
+
status: 300,
|
360
|
+
},
|
361
|
+
'1.2.3.12' => {
|
362
|
+
body: 'Cannot satisfy your Accept-Charset requirements',
|
363
|
+
headers: {},
|
364
|
+
status: 406,
|
365
|
+
},
|
366
|
+
'1.2.3.13' => {
|
367
|
+
body: JSON.generate({
|
368
|
+
'code' => 'IP_ADDRESS_NOT_FOUND',
|
369
|
+
'error' => 'The address "1.2.3.13" is not in our database.',
|
370
|
+
}),
|
371
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
372
|
+
status: 400,
|
373
|
+
},
|
374
|
+
'1.2.3.14' => {
|
375
|
+
body: JSON.generate({
|
376
|
+
'code' => 'IP_ADDRESS_RESERVED',
|
377
|
+
'error' => 'The address "1.2.3.14" is a private address.',
|
378
|
+
}),
|
379
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
380
|
+
status: 400,
|
381
|
+
},
|
382
|
+
'1.2.3.15' => {
|
383
|
+
body: JSON.generate({
|
384
|
+
'code' => 'AUTHORIZATION_INVALID',
|
385
|
+
'error' => 'An account ID and license key are required to use this service.',
|
386
|
+
}),
|
387
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
388
|
+
status: 401,
|
389
|
+
},
|
390
|
+
'1.2.3.16' => {
|
391
|
+
body: JSON.generate({
|
392
|
+
'code' => 'LICENSE_KEY_REQUIRED',
|
393
|
+
'error' => 'A license key is required to use this service.',
|
394
|
+
}),
|
395
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
396
|
+
status: 401,
|
397
|
+
},
|
398
|
+
'1.2.3.17' => {
|
399
|
+
body: JSON.generate({
|
400
|
+
'code' => 'ACCOUNT_ID_REQUIRED',
|
401
|
+
'error' => 'An account ID is required to use this service.',
|
402
|
+
}),
|
403
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
404
|
+
status: 401,
|
405
|
+
},
|
406
|
+
'1.2.3.18' => {
|
407
|
+
body: JSON.generate({
|
408
|
+
'code' => 'INSUFFICIENT_FUNDS',
|
409
|
+
'error' => 'The license key you have provided is out of queries.',
|
410
|
+
}),
|
411
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
412
|
+
status: 402,
|
413
|
+
},
|
414
|
+
'1.2.3.19' => {
|
415
|
+
body: JSON.generate({
|
416
|
+
'code' => 'UNEXPECTED',
|
417
|
+
'error' => 'Whoa!',
|
418
|
+
}),
|
419
|
+
headers: { 'Content-Type': CONTENT_TYPES[:country] },
|
420
|
+
status: 400,
|
421
|
+
},
|
422
|
+
}
|
423
|
+
|
424
|
+
responses[ip_address]
|
425
|
+
end
|
426
|
+
end
|