rdap 0.1.5 → 1.0.1

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.
data/data/ipv4.json ADDED
@@ -0,0 +1,265 @@
1
+ {
2
+ "description": "RDAP bootstrap file for IPv4 address allocations",
3
+ "publication": "2019-06-07T19:00:02Z",
4
+ "services": [
5
+ [
6
+ [
7
+ "41.0.0.0/8",
8
+ "102.0.0.0/8",
9
+ "105.0.0.0/8",
10
+ "154.0.0.0/8",
11
+ "196.0.0.0/8",
12
+ "197.0.0.0/8"
13
+ ],
14
+ [
15
+ "https://rdap.afrinic.net/rdap/",
16
+ "http://rdap.afrinic.net/rdap/"
17
+ ]
18
+ ],
19
+ [
20
+ [
21
+ "1.0.0.0/8",
22
+ "14.0.0.0/8",
23
+ "27.0.0.0/8",
24
+ "36.0.0.0/8",
25
+ "39.0.0.0/8",
26
+ "42.0.0.0/8",
27
+ "43.0.0.0/8",
28
+ "49.0.0.0/8",
29
+ "58.0.0.0/8",
30
+ "59.0.0.0/8",
31
+ "60.0.0.0/8",
32
+ "61.0.0.0/8",
33
+ "101.0.0.0/8",
34
+ "103.0.0.0/8",
35
+ "106.0.0.0/8",
36
+ "110.0.0.0/8",
37
+ "111.0.0.0/8",
38
+ "112.0.0.0/8",
39
+ "113.0.0.0/8",
40
+ "114.0.0.0/8",
41
+ "115.0.0.0/8",
42
+ "116.0.0.0/8",
43
+ "117.0.0.0/8",
44
+ "118.0.0.0/8",
45
+ "119.0.0.0/8",
46
+ "120.0.0.0/8",
47
+ "121.0.0.0/8",
48
+ "122.0.0.0/8",
49
+ "123.0.0.0/8",
50
+ "124.0.0.0/8",
51
+ "125.0.0.0/8",
52
+ "126.0.0.0/8",
53
+ "133.0.0.0/8",
54
+ "150.0.0.0/8",
55
+ "153.0.0.0/8",
56
+ "163.0.0.0/8",
57
+ "171.0.0.0/8",
58
+ "175.0.0.0/8",
59
+ "180.0.0.0/8",
60
+ "182.0.0.0/8",
61
+ "183.0.0.0/8",
62
+ "202.0.0.0/8",
63
+ "203.0.0.0/8",
64
+ "210.0.0.0/8",
65
+ "211.0.0.0/8",
66
+ "218.0.0.0/8",
67
+ "219.0.0.0/8",
68
+ "220.0.0.0/8",
69
+ "221.0.0.0/8",
70
+ "222.0.0.0/8",
71
+ "223.0.0.0/8"
72
+ ],
73
+ [
74
+ "https://rdap.apnic.net/"
75
+ ]
76
+ ],
77
+ [
78
+ [
79
+ "3.0.0.0/8",
80
+ "4.0.0.0/8",
81
+ "6.0.0.0/8",
82
+ "7.0.0.0/8",
83
+ "8.0.0.0/8",
84
+ "9.0.0.0/8",
85
+ "11.0.0.0/8",
86
+ "12.0.0.0/8",
87
+ "13.0.0.0/8",
88
+ "15.0.0.0/8",
89
+ "16.0.0.0/8",
90
+ "17.0.0.0/8",
91
+ "18.0.0.0/8",
92
+ "19.0.0.0/8",
93
+ "20.0.0.0/8",
94
+ "21.0.0.0/8",
95
+ "22.0.0.0/8",
96
+ "23.0.0.0/8",
97
+ "24.0.0.0/8",
98
+ "26.0.0.0/8",
99
+ "28.0.0.0/8",
100
+ "29.0.0.0/8",
101
+ "30.0.0.0/8",
102
+ "32.0.0.0/8",
103
+ "33.0.0.0/8",
104
+ "34.0.0.0/8",
105
+ "35.0.0.0/8",
106
+ "38.0.0.0/8",
107
+ "40.0.0.0/8",
108
+ "44.0.0.0/8",
109
+ "45.0.0.0/8",
110
+ "47.0.0.0/8",
111
+ "48.0.0.0/8",
112
+ "50.0.0.0/8",
113
+ "52.0.0.0/8",
114
+ "54.0.0.0/8",
115
+ "55.0.0.0/8",
116
+ "56.0.0.0/8",
117
+ "63.0.0.0/8",
118
+ "64.0.0.0/8",
119
+ "65.0.0.0/8",
120
+ "66.0.0.0/8",
121
+ "67.0.0.0/8",
122
+ "68.0.0.0/8",
123
+ "69.0.0.0/8",
124
+ "70.0.0.0/8",
125
+ "71.0.0.0/8",
126
+ "72.0.0.0/8",
127
+ "73.0.0.0/8",
128
+ "74.0.0.0/8",
129
+ "75.0.0.0/8",
130
+ "76.0.0.0/8",
131
+ "96.0.0.0/8",
132
+ "97.0.0.0/8",
133
+ "98.0.0.0/8",
134
+ "99.0.0.0/8",
135
+ "100.0.0.0/8",
136
+ "104.0.0.0/8",
137
+ "107.0.0.0/8",
138
+ "108.0.0.0/8",
139
+ "128.0.0.0/8",
140
+ "129.0.0.0/8",
141
+ "130.0.0.0/8",
142
+ "131.0.0.0/8",
143
+ "132.0.0.0/8",
144
+ "134.0.0.0/8",
145
+ "135.0.0.0/8",
146
+ "136.0.0.0/8",
147
+ "137.0.0.0/8",
148
+ "138.0.0.0/8",
149
+ "139.0.0.0/8",
150
+ "140.0.0.0/8",
151
+ "142.0.0.0/8",
152
+ "143.0.0.0/8",
153
+ "144.0.0.0/8",
154
+ "146.0.0.0/8",
155
+ "147.0.0.0/8",
156
+ "148.0.0.0/8",
157
+ "149.0.0.0/8",
158
+ "152.0.0.0/8",
159
+ "155.0.0.0/8",
160
+ "156.0.0.0/8",
161
+ "157.0.0.0/8",
162
+ "158.0.0.0/8",
163
+ "159.0.0.0/8",
164
+ "160.0.0.0/8",
165
+ "161.0.0.0/8",
166
+ "162.0.0.0/8",
167
+ "164.0.0.0/8",
168
+ "165.0.0.0/8",
169
+ "166.0.0.0/8",
170
+ "167.0.0.0/8",
171
+ "168.0.0.0/8",
172
+ "169.0.0.0/8",
173
+ "170.0.0.0/8",
174
+ "172.0.0.0/8",
175
+ "173.0.0.0/8",
176
+ "174.0.0.0/8",
177
+ "184.0.0.0/8",
178
+ "192.0.0.0/8",
179
+ "198.0.0.0/8",
180
+ "199.0.0.0/8",
181
+ "204.0.0.0/8",
182
+ "205.0.0.0/8",
183
+ "206.0.0.0/8",
184
+ "207.0.0.0/8",
185
+ "208.0.0.0/8",
186
+ "209.0.0.0/8",
187
+ "214.0.0.0/8",
188
+ "215.0.0.0/8",
189
+ "216.0.0.0/8"
190
+ ],
191
+ [
192
+ "https://rdap.arin.net/registry/",
193
+ "http://rdap.arin.net/registry/"
194
+ ]
195
+ ],
196
+ [
197
+ [
198
+ "2.0.0.0/8",
199
+ "5.0.0.0/8",
200
+ "25.0.0.0/8",
201
+ "31.0.0.0/8",
202
+ "37.0.0.0/8",
203
+ "46.0.0.0/8",
204
+ "51.0.0.0/8",
205
+ "53.0.0.0/8",
206
+ "57.0.0.0/8",
207
+ "62.0.0.0/8",
208
+ "77.0.0.0/8",
209
+ "78.0.0.0/8",
210
+ "79.0.0.0/8",
211
+ "80.0.0.0/8",
212
+ "81.0.0.0/8",
213
+ "82.0.0.0/8",
214
+ "83.0.0.0/8",
215
+ "84.0.0.0/8",
216
+ "85.0.0.0/8",
217
+ "86.0.0.0/8",
218
+ "87.0.0.0/8",
219
+ "88.0.0.0/8",
220
+ "89.0.0.0/8",
221
+ "90.0.0.0/8",
222
+ "91.0.0.0/8",
223
+ "92.0.0.0/8",
224
+ "93.0.0.0/8",
225
+ "94.0.0.0/8",
226
+ "95.0.0.0/8",
227
+ "109.0.0.0/8",
228
+ "141.0.0.0/8",
229
+ "145.0.0.0/8",
230
+ "151.0.0.0/8",
231
+ "176.0.0.0/8",
232
+ "178.0.0.0/8",
233
+ "185.0.0.0/8",
234
+ "188.0.0.0/8",
235
+ "193.0.0.0/8",
236
+ "194.0.0.0/8",
237
+ "195.0.0.0/8",
238
+ "212.0.0.0/8",
239
+ "213.0.0.0/8",
240
+ "217.0.0.0/8"
241
+ ],
242
+ [
243
+ "https://rdap.db.ripe.net/"
244
+ ]
245
+ ],
246
+ [
247
+ [
248
+ "177.0.0.0/8",
249
+ "179.0.0.0/8",
250
+ "181.0.0.0/8",
251
+ "186.0.0.0/8",
252
+ "187.0.0.0/8",
253
+ "189.0.0.0/8",
254
+ "190.0.0.0/8",
255
+ "191.0.0.0/8",
256
+ "200.0.0.0/8",
257
+ "201.0.0.0/8"
258
+ ],
259
+ [
260
+ "https://rdap.lacnic.net/rdap/"
261
+ ]
262
+ ]
263
+ ],
264
+ "version": "1.0"
265
+ }
data/data/ipv6.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "description": "RDAP bootstrap file for IPv6 address allocations",
3
+ "publication": "2024-11-01T22:00:01Z",
4
+ "services": [
5
+ [
6
+ [
7
+ "2001:4200::/23",
8
+ "2c00::/12"
9
+ ],
10
+ [
11
+ "https://rdap.afrinic.net/rdap/",
12
+ "http://rdap.afrinic.net/rdap/"
13
+ ]
14
+ ],
15
+ [
16
+ [
17
+ "2001:200::/23",
18
+ "2001:4400::/23",
19
+ "2001:8000::/19",
20
+ "2001:a000::/20",
21
+ "2001:b000::/20",
22
+ "2001:c00::/23",
23
+ "2001:e00::/23",
24
+ "2400::/12",
25
+ "2410::/12"
26
+ ],
27
+ [
28
+ "https://rdap.apnic.net/"
29
+ ]
30
+ ],
31
+ [
32
+ [
33
+ "2001:1800::/23",
34
+ "2001:400::/23",
35
+ "2001:4800::/23",
36
+ "2600::/12",
37
+ "2610::/23",
38
+ "2620::/23",
39
+ "2630::/12"
40
+ ],
41
+ [
42
+ "https://rdap.arin.net/registry/",
43
+ "http://rdap.arin.net/registry/"
44
+ ]
45
+ ],
46
+ [
47
+ [
48
+ "2001:1400::/22",
49
+ "2001:1a00::/23",
50
+ "2001:1c00::/22",
51
+ "2001:2000::/19",
52
+ "2001:4000::/23",
53
+ "2001:4600::/23",
54
+ "2001:4a00::/23",
55
+ "2001:4c00::/23",
56
+ "2001:5000::/20",
57
+ "2001:600::/23",
58
+ "2001:800::/22",
59
+ "2003::/18",
60
+ "2a00::/12",
61
+ "2a10::/12"
62
+ ],
63
+ [
64
+ "https://rdap.db.ripe.net/"
65
+ ]
66
+ ],
67
+ [
68
+ [
69
+ "2001:1200::/23",
70
+ "2800::/12"
71
+ ],
72
+ [
73
+ "https://rdap.lacnic.net/rdap/"
74
+ ]
75
+ ]
76
+ ],
77
+ "version": "1.0"
78
+ }
data/lib/rdap.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
+ require 'ipaddr'
3
4
 
4
5
  module RDAP
5
- VERSION = "0.1.5"
6
+ VERSION = "1.0.1"
6
7
  BOOTSTRAP = "https://rdap.org/"
7
8
  TYPES = [:domain, :ip, :autnum].freeze
8
9
  HEADERS = {
@@ -14,31 +15,71 @@ module RDAP
14
15
  class Error < StandardError; end
15
16
  class ServerError < Error; end
16
17
  class SSLError < ServerError; end
18
+ class ConnectionError < ServerError; end
17
19
  class EmptyResponse < ServerError; end
18
20
  class InvalidResponse < ServerError; end
19
21
  class NotFound < Error; end
20
22
  class TooManyRequests < Error; end
21
23
 
22
- def self.domain name, **opts
23
- query name, type: :domain, **opts
24
+ def self.domain name, server: nil, **opts
25
+ tld = name.to_s.chomp('.').split('.').last
26
+ server ||= dns_index[tld.downcase] if tld
27
+ query name, type: :domain, server: server, **opts
24
28
  end
25
29
 
26
- def self.ip name, **opts
27
- query name, type: :ip, **opts
30
+ def self.ip name, server: nil, **opts
31
+ ip = IPAddr.new(name.to_s)
32
+ server ||= ip_index(ip.ipv6? ? 'ipv6' : 'ipv4').find { |net, _| net.include?(ip) }&.last
33
+ query name, type: :ip, server: server, **opts
28
34
  end
29
35
 
30
- def self.as name, **opts
31
- query name, type: :autnum, **opts
36
+ def self.as name, server: nil, **opts
37
+ asn = name.to_i if name.is_a?(Integer) || name.to_s =~ /\A\d+\z/
38
+ raise ArgumentError.new("RDAP: Invalid AS number: #{name.inspect}") unless asn
39
+ server ||= asn_index.find { |range, _| range.cover?(asn) }&.last
40
+ query name, type: :autnum, server: server, **opts
32
41
  end
33
42
 
34
- def self.query name, type:, timeout: 5, server: BOOTSTRAP, headers: {}
43
+ def self.query name, type:, timeout: 5, server: nil, headers: {}
35
44
  TYPES.include?(type) or raise ArgumentError.new("RDAP: Invalid query type: #{type}, supported types: #{TYPES}")
45
+ # .domain/.ip/.as resolve the authoritative server from the bundled IANA
46
+ # files; fall back to the public bootstrap server for anything not covered.
47
+ server ||= BOOTSTRAP
36
48
  uri = URI("#{server.chomp('/')}/#{type}/#{name}")
37
49
  get_follow_redirects(uri, timeout: timeout, headers: headers)
38
50
  end
39
51
 
40
52
  private
41
53
 
54
+ # TLD => RDAP server, built once for O(1) domain lookups. IANA lists the
55
+ # preferred (https) endpoint first, so urls.first is the server to use.
56
+ def self.dns_index
57
+ @dns_index ||= bootstrap('dns').each_with_object({}) do |(labels, urls), index|
58
+ labels.each { |label| index[label.downcase] = urls.first }
59
+ end
60
+ end
61
+
62
+ # [network, RDAP server] pairs for a registry, built once so the CIDRs are
63
+ # parsed into IPAddr objects a single time rather than on every lookup.
64
+ def self.ip_index registry
65
+ (@ip_index ||= {})[registry] ||= bootstrap(registry).flat_map do |cidrs, urls|
66
+ cidrs.map { |cidr| [IPAddr.new(cidr), urls.first] }
67
+ end
68
+ end
69
+
70
+ # [AS range, RDAP server] pairs, built once so the ranges are parsed a single
71
+ # time rather than on every lookup.
72
+ def self.asn_index
73
+ @asn_index ||= bootstrap('asn').flat_map do |ranges, urls|
74
+ ranges.map { |range| low, high = range.split('-'); [(low.to_i..(high || low).to_i), urls.first] }
75
+ end
76
+ end
77
+
78
+ # Service entries from a bundled IANA bootstrap file (https://data.iana.org/rdap/).
79
+ def self.bootstrap registry
80
+ JSON.parse(File.read(File.expand_path("../data/#{registry}.json", __dir__)))["services"]
81
+ end
82
+
42
83
  def self.get_follow_redirects uri, timeout: 5, headers: {}, redirection_limit: 5
43
84
  raise ServerError.new("Too many redirections (> #{redirection_limit}) at #{uri}") if redirection_limit == 0
44
85
 
@@ -77,5 +118,8 @@ module RDAP
77
118
  raise SSLError.new("#{e.message} (#{uri.host})")
78
119
  rescue JSON::ParserError => e
79
120
  raise InvalidResponse.new("JSON parser error: #{e.message}")
121
+ rescue Timeout::Error, IOError, SocketError, SystemCallError => e
122
+ # Transport failures (timeouts, DNS, connection reset/refused, EOF, ...)
123
+ raise ConnectionError.new("#{e.class}: #{e.message} (#{uri.host})")
80
124
  end
81
125
  end
metadata CHANGED
@@ -1,35 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrien Rey-Jarthon
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2022-12-29 00:00:00.000000000 Z
10
+ date: 2026-09-10 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description:
14
12
  email:
15
13
  - jobs@adrienjarthon.com
16
14
  executables: []
17
15
  extensions: []
18
16
  extra_rdoc_files: []
19
17
  files:
20
- - ".gitignore"
21
- - ".travis.yml"
22
- - Gemfile
23
- - Gemfile.lock
24
- - README.md
25
- - Rakefile
26
- - bin/console
18
+ - data/asn.json
19
+ - data/dns.json
20
+ - data/ipv4.json
21
+ - data/ipv6.json
27
22
  - lib/rdap.rb
28
- - rdap.gemspec
29
23
  homepage: https://github.com/jarthod/rdap
30
24
  licenses: []
31
25
  metadata: {}
32
- post_install_message:
33
26
  rdoc_options: []
34
27
  require_paths:
35
28
  - lib
@@ -37,15 +30,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
37
30
  requirements:
38
31
  - - ">="
39
32
  - !ruby/object:Gem::Version
40
- version: 2.3.0
33
+ version: 3.2.0
41
34
  required_rubygems_version: !ruby/object:Gem::Requirement
42
35
  requirements:
43
36
  - - ">="
44
37
  - !ruby/object:Gem::Version
45
38
  version: '0'
46
39
  requirements: []
47
- rubygems_version: 3.3.7
48
- signing_key:
40
+ rubygems_version: 3.6.2
49
41
  specification_version: 4
50
42
  summary: A minimal Ruby client to query RDAP APIs though a bootstrap server
51
43
  test_files: []
data/.gitignore DELETED
@@ -1,8 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- # Ubuntu 18.04
5
- dist: bionic
6
- # https://docs.travis-ci.com/user/reference/bionic/#ruby-support
7
- rvm:
8
- - 2.6.5
9
- - 2.7.0
10
- - 3.0.3
11
- before_install: gem install bundler -v 2.1.4
data/Gemfile DELETED
@@ -1,9 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in rdap.gemspec
4
- gemspec
5
-
6
- gem "rake", ">= 12.0"
7
- gem "rspec", "~> 3.0"
8
- gem "vcr", "~> 6.0"
9
- gem "webmock"
data/Gemfile.lock DELETED
@@ -1,48 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rdap (0.1.4)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- addressable (2.8.1)
10
- public_suffix (>= 2.0.2, < 6.0)
11
- crack (0.4.5)
12
- rexml
13
- diff-lcs (1.5.0)
14
- hashdiff (1.0.1)
15
- public_suffix (5.0.1)
16
- rake (13.0.6)
17
- rexml (3.2.5)
18
- rspec (3.12.0)
19
- rspec-core (~> 3.12.0)
20
- rspec-expectations (~> 3.12.0)
21
- rspec-mocks (~> 3.12.0)
22
- rspec-core (3.12.0)
23
- rspec-support (~> 3.12.0)
24
- rspec-expectations (3.12.1)
25
- diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.12.0)
27
- rspec-mocks (3.12.1)
28
- diff-lcs (>= 1.2.0, < 2.0)
29
- rspec-support (~> 3.12.0)
30
- rspec-support (3.12.0)
31
- vcr (6.1.0)
32
- webmock (3.18.1)
33
- addressable (>= 2.8.0)
34
- crack (>= 0.3.2)
35
- hashdiff (>= 0.4.0, < 2.0.0)
36
-
37
- PLATFORMS
38
- ruby
39
-
40
- DEPENDENCIES
41
- rake (>= 12.0)
42
- rdap!
43
- rspec (~> 3.0)
44
- vcr (~> 6.0)
45
- webmock
46
-
47
- BUNDLED WITH
48
- 2.1.4