whois 4.0.6 → 6.0.3
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/.github/FUNDING.yml +12 -0
- data/.github/dependabot.yml +17 -0
- data/.github/workflows/release.yml +19 -0
- data/.github/workflows/tests.yml +29 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.rubocop.yml +27 -0
- data/.rubocop_opinionated.yml +115 -0
- data/.rubocop_todo.yml +89 -0
- data/.simplecov +6 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +147 -44
- data/CONTRIBUTING.md +18 -6
- data/Gemfile +8 -0
- data/LICENSE.txt +1 -1
- data/README.md +4 -4
- data/Rakefile +28 -0
- data/SECURITY.md +24 -0
- data/bin/console +1 -0
- data/bin/whoisrb +6 -5
- data/data/ipv4.json +1 -3
- data/data/tld.json +125 -1049
- data/lib/whois/client.rb +5 -7
- data/lib/whois/errors.rb +4 -6
- data/lib/whois/record/part.rb +5 -6
- data/lib/whois/record.rb +5 -8
- data/lib/whois/server/adapters/afilias.rb +4 -5
- data/lib/whois/server/adapters/arin.rb +7 -8
- data/lib/whois/server/adapters/arpa.rb +19 -24
- data/lib/whois/server/adapters/base.rb +29 -46
- data/lib/whois/server/adapters/formatted.rb +4 -6
- data/lib/whois/server/adapters/none.rb +4 -6
- data/lib/whois/server/adapters/not_implemented.rb +4 -6
- data/lib/whois/server/adapters/standard.rb +4 -6
- data/lib/whois/server/adapters/verisign.rb +4 -5
- data/lib/whois/server/adapters/web.rb +4 -6
- data/lib/whois/server/socket_handler.rb +11 -12
- data/lib/whois/server.rb +73 -64
- data/lib/whois/version.rb +4 -2
- data/lib/whois.rb +32 -33
- data/spec/fixtures/referrals/afilias.bz.txt +23 -0
- data/spec/fixtures/referrals/arin_referral_apnic.txt +78 -0
- data/spec/fixtures/referrals/arin_referral_missing.txt +52 -0
- data/spec/fixtures/referrals/arin_referral_ripe.txt +50 -0
- data/spec/fixtures/referrals/arin_referral_rwhois.txt +63 -0
- data/spec/fixtures/referrals/arin_referral_servernap.txt +63 -0
- data/spec/fixtures/referrals/arin_referral_whois.txt +56 -0
- data/spec/fixtures/referrals/crsnic.com.txt +60 -0
- data/spec/fixtures/referrals/crsnic.com_referral.txt +56 -0
- data/spec/fixtures/referrals/crsnic.com_referral_missing.txt +50 -0
- data/spec/integration/whois_spec.rb +73 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/helpers/connectivity_helper.rb +15 -0
- data/spec/support/helpers/spec_helper.rb +31 -0
- data/spec/whois/client_spec.rb +143 -0
- data/spec/whois/record/part_spec.rb +38 -0
- data/spec/whois/record_spec.rb +168 -0
- data/spec/whois/server/adapters/afilias_spec.rb +49 -0
- data/spec/whois/server/adapters/arin_spec.rb +83 -0
- data/spec/whois/server/adapters/arpa_spec.rb +29 -0
- data/spec/whois/server/adapters/base_spec.rb +155 -0
- data/spec/whois/server/adapters/formatted_spec.rb +53 -0
- data/spec/whois/server/adapters/none_spec.rb +23 -0
- data/spec/whois/server/adapters/not_implemented_spec.rb +24 -0
- data/spec/whois/server/adapters/standard_spec.rb +42 -0
- data/spec/whois/server/adapters/verisign_spec.rb +60 -0
- data/spec/whois/server/adapters/web_spec.rb +24 -0
- data/spec/whois/server/socket_handler_spec.rb +33 -0
- data/spec/whois/server_spec.rb +302 -0
- data/spec/whois/web_interface_error_spec.rb +23 -0
- data/spec/whois/whois_spec.rb +15 -0
- data/utils/compare-whois.rb +30 -0
- data/utils/deftld.rb +230 -0
- data/utils/defutils.rb +26 -0
- data/utils/fixupd.rb +60 -0
- data/utils/matrix.rb +68 -0
- data/utils/mkwhois.rb +31 -0
- data/whois.gemspec +19 -32
- metadata +58 -11
- data/4.0-Upgrade.md +0 -143
- data/bin/setup +0 -8
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Client do
|
|
6
|
+
describe "#initialize" do
|
|
7
|
+
it "accepts a zero parameters" do
|
|
8
|
+
expect { described_class.new }.not_to raise_error
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "accepts a settings parameter" do
|
|
12
|
+
expect { described_class.new({ foo: "bar" }) }.not_to raise_error
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
it "accepts a timeout setting with a value in seconds" do
|
|
17
|
+
client = described_class.new(timeout: 100)
|
|
18
|
+
expect(client.timeout).to eq(100)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "accepts a timeout setting with a nil value" do
|
|
22
|
+
client = described_class.new(timeout: nil)
|
|
23
|
+
expect(client.timeout).to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "accepts a block" do
|
|
27
|
+
described_class.new do |client|
|
|
28
|
+
expect(client).to be_instance_of(described_class)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
it "defaults timeout setting to DEFAULT_TIMEOUT" do
|
|
34
|
+
client = described_class.new
|
|
35
|
+
expect(client.timeout).to eq(described_class::DEFAULT_TIMEOUT)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "sets settings to given argument, except timeout" do
|
|
39
|
+
client = described_class.new(timeout: nil, foo: "bar")
|
|
40
|
+
expect(client.settings).to eq({ foo: "bar" })
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#lookup" do
|
|
45
|
+
it "converts the argument to string" do
|
|
46
|
+
query = ["example", ".", "test"]
|
|
47
|
+
query.instance_eval do
|
|
48
|
+
def to_s
|
|
49
|
+
join
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
server = Whois::Server::Adapters::Base.new(:tld, "test", "whois.test")
|
|
54
|
+
expect(server).to receive(:lookup).with("example.test")
|
|
55
|
+
expect(Whois::Server).to receive(:guess).with("example.test").and_return(server)
|
|
56
|
+
|
|
57
|
+
described_class.new.lookup(query)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "converts the argument to downcase" do
|
|
61
|
+
server = Whois::Server::Adapters::Base.new(:tld, "test", "whois.test")
|
|
62
|
+
expect(server).to receive(:lookup).with("example.test")
|
|
63
|
+
expect(Whois::Server).to receive(:guess).with("example.test").and_return(server)
|
|
64
|
+
|
|
65
|
+
described_class.new.lookup("Example.TEST")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "detects email" do
|
|
69
|
+
expect {
|
|
70
|
+
described_class.new.lookup("weppos@weppos.net")
|
|
71
|
+
}.to raise_error(Whois::ServerNotSupported)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "works with domain with no whois" do
|
|
75
|
+
Whois::Server.define(:tld, "nowhois", nil, adapter: Whois::Server::Adapters::None)
|
|
76
|
+
|
|
77
|
+
expect {
|
|
78
|
+
described_class.new.lookup("domain.nowhois")
|
|
79
|
+
}.to raise_error(Whois::NoInterfaceError, /no whois server/)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "works with domain with web whois" do
|
|
83
|
+
Whois::Server.define(:tld, "webwhois", nil, adapter: Whois::Server::Adapters::Web, url: "http://www.example.com/")
|
|
84
|
+
|
|
85
|
+
expect {
|
|
86
|
+
described_class.new.lookup("domain.webwhois")
|
|
87
|
+
}.to raise_error(Whois::WebInterfaceError, /www\.example\.com/)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "raises if timeout is exceeded" do
|
|
91
|
+
adapter = Class.new(Whois::Server::Adapters::Base) do
|
|
92
|
+
def lookup(*)
|
|
93
|
+
sleep(2)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
expect(Whois::Server).to receive(:guess).and_return(adapter.new(:tld, "test", "whois.test"))
|
|
97
|
+
|
|
98
|
+
client = described_class.new(timeout: 1)
|
|
99
|
+
expect {
|
|
100
|
+
client.lookup("example.test")
|
|
101
|
+
}.to raise_error(Timeout::Error)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "does not raise if timeout is not exceeded" do
|
|
105
|
+
adapter = Class.new(Whois::Server::Adapters::Base) do
|
|
106
|
+
def lookup(*)
|
|
107
|
+
sleep(1)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
expect(Whois::Server).to receive(:guess).and_return(adapter.new(:tld, "test", "whois.test"))
|
|
111
|
+
|
|
112
|
+
client = described_class.new(timeout: 5)
|
|
113
|
+
expect {
|
|
114
|
+
client.lookup("example.test")
|
|
115
|
+
}.not_to raise_error
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "supports unlimited timeout" do
|
|
119
|
+
adapter = Class.new(Whois::Server::Adapters::Base) do
|
|
120
|
+
def lookup(*)
|
|
121
|
+
sleep(1)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
expect(Whois::Server).to receive(:guess).and_return(adapter.new(:tld, "test", "whois.test"))
|
|
125
|
+
|
|
126
|
+
client = described_class.new.tap { |c| c.timeout = nil }
|
|
127
|
+
expect {
|
|
128
|
+
client.lookup("example.test")
|
|
129
|
+
}.not_to raise_error
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# FIXME: use RSpec metadata
|
|
134
|
+
need_connectivity do
|
|
135
|
+
describe "#query" do
|
|
136
|
+
it "sends a query for given domain" do
|
|
137
|
+
record = described_class.new.lookup("weppos.it")
|
|
138
|
+
expect(record.match?(/Domain:\s+weppos\.it/)).to be(true)
|
|
139
|
+
expect(record.match?(/Created:/)).to be(true)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Record::Part do
|
|
6
|
+
describe "#initialize" do
|
|
7
|
+
it "accepts an empty value" do
|
|
8
|
+
expect {
|
|
9
|
+
instance = described_class.new
|
|
10
|
+
expect(instance.body).to be_nil
|
|
11
|
+
}.not_to raise_error
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "accepts an empty hash" do
|
|
15
|
+
expect {
|
|
16
|
+
instance = described_class.new({})
|
|
17
|
+
expect(instance.body).to be_nil
|
|
18
|
+
}.not_to raise_error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "initializes a new instance from given hash" do
|
|
22
|
+
instance = described_class.new(body: "This is a WHOIS record.", host: "whois.example.test")
|
|
23
|
+
|
|
24
|
+
expect(instance.body).to eq("This is a WHOIS record.")
|
|
25
|
+
expect(instance.host).to eq("whois.example.test")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "initializes a new instance from given block" do
|
|
29
|
+
instance = described_class.new do |c|
|
|
30
|
+
c.body = "This is a WHOIS record."
|
|
31
|
+
c.host = "whois.example.test"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
expect(instance.body).to eq("This is a WHOIS record.")
|
|
35
|
+
expect(instance.host).to eq("whois.example.test")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Record do
|
|
6
|
+
subject { described_class.new(server, parts) }
|
|
7
|
+
|
|
8
|
+
let(:server) {
|
|
9
|
+
Whois::Server.factory(:tld, ".foo", "whois.example.test")
|
|
10
|
+
}
|
|
11
|
+
let(:parts) {
|
|
12
|
+
[
|
|
13
|
+
Whois::Record::Part.new(body: "This is a record from foo.", host: "foo.example.test"),
|
|
14
|
+
Whois::Record::Part.new(body: "This is a record from bar.", host: "bar.example.test"),
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
let(:content) {
|
|
18
|
+
parts.map(&:body).join("\n")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
describe "#initialize" do
|
|
23
|
+
it "requires a server and parts" do
|
|
24
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
|
25
|
+
expect { described_class.new(server) }.to raise_error(ArgumentError)
|
|
26
|
+
expect { described_class.new(server, parts) }.not_to raise_error
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "sets server and parts from arguments" do
|
|
30
|
+
instance = described_class.new(server, parts)
|
|
31
|
+
expect(instance.server).to be(server)
|
|
32
|
+
expect(instance.parts).to be(parts)
|
|
33
|
+
|
|
34
|
+
instance = described_class.new(nil, nil)
|
|
35
|
+
expect(instance.server).to be_nil
|
|
36
|
+
expect(instance.parts).to be_nil
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
describe "#to_s" do
|
|
42
|
+
it "delegates to #content" do
|
|
43
|
+
expect(described_class.new(nil, [parts[0]]).to_s).to eq(parts[0].body)
|
|
44
|
+
expect(described_class.new(nil, parts).to_s).to eq(parts.map(&:body).join("\n"))
|
|
45
|
+
expect(described_class.new(nil, []).to_s).to eq("")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#inspect" do
|
|
50
|
+
it "inspects the record content" do
|
|
51
|
+
expect(described_class.new(nil, [parts[0]]).inspect).to eq(parts[0].body.inspect)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "joins multiple parts" do
|
|
55
|
+
expect(described_class.new(nil, parts).inspect).to eq(parts.map(&:body).join("\n").inspect)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "joins empty parts" do
|
|
59
|
+
expect(described_class.new(nil, []).inspect).to eq("".inspect)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "#==" do
|
|
64
|
+
it "returns true when other is the same instance" do
|
|
65
|
+
one = two = described_class.new(server, parts)
|
|
66
|
+
|
|
67
|
+
expect(one == two).to be_truthy
|
|
68
|
+
expect(one).to eql(two)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "returns true when other has same class and has the same parts" do
|
|
72
|
+
one = described_class.new(server, parts)
|
|
73
|
+
two = described_class.new(server, parts)
|
|
74
|
+
|
|
75
|
+
expect(one == two).to be_truthy
|
|
76
|
+
expect(one).to eql(two)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "returns true when other has descendant class and has the same parts" do
|
|
80
|
+
subklass = Class.new(described_class)
|
|
81
|
+
one = described_class.new(server, parts)
|
|
82
|
+
two = subklass.new(server, parts)
|
|
83
|
+
|
|
84
|
+
expect(one == two).to be_truthy
|
|
85
|
+
expect(one).to eql(two)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "returns true when other has same class and has equal parts" do
|
|
89
|
+
one = described_class.new(server, parts)
|
|
90
|
+
two = described_class.new(server, parts.dup)
|
|
91
|
+
|
|
92
|
+
expect(one == two).to be_truthy
|
|
93
|
+
expect(one).to eql(two)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "returns true when other has same class, different server and the same parts" do
|
|
97
|
+
one = described_class.new(server, parts)
|
|
98
|
+
two = described_class.new(nil, parts)
|
|
99
|
+
|
|
100
|
+
expect(one == two).to be_truthy
|
|
101
|
+
expect(one).to eql(two)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "returns false when other has different class and has the same parts" do
|
|
105
|
+
one = described_class.new(server, parts)
|
|
106
|
+
two = Struct.new(:server, :parts).new(server, parts)
|
|
107
|
+
|
|
108
|
+
expect(one == two).to be_falsey
|
|
109
|
+
expect(one).not_to eql(two)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "returns false when other has different parts" do
|
|
113
|
+
one = described_class.new(server, parts)
|
|
114
|
+
two = described_class.new(server, [])
|
|
115
|
+
|
|
116
|
+
expect(one == two).to be_falsey
|
|
117
|
+
expect(one).not_to eql(two)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "returns false when other is string and has the same content" do
|
|
121
|
+
one = described_class.new(server, parts)
|
|
122
|
+
two = described_class.new(server, parts).to_s
|
|
123
|
+
|
|
124
|
+
expect(one == two).to be_falsey
|
|
125
|
+
expect(one).not_to eql(two)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "returns false when other is string and has different content" do
|
|
129
|
+
one = described_class.new(server, parts)
|
|
130
|
+
two = "different"
|
|
131
|
+
|
|
132
|
+
expect(one == two).to be_falsey
|
|
133
|
+
expect(one).not_to eql(two)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
describe "#match" do
|
|
139
|
+
it "delegates to content" do
|
|
140
|
+
expect(subject.match(/record/)).to be_a(MatchData)
|
|
141
|
+
expect(subject.match(/record/)[0]).to eq("record")
|
|
142
|
+
|
|
143
|
+
expect(subject.match(/nomatch/)).to be_nil
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe "#match?" do
|
|
148
|
+
it "calls match and checks for match" do
|
|
149
|
+
expect(subject.match?(/record/)).to be(true)
|
|
150
|
+
expect(subject.match?(/nomatch/)).to be(false)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
describe "#content" do
|
|
156
|
+
it "returns the part body" do
|
|
157
|
+
expect(described_class.new(nil, [parts[0]]).content).to eq(parts[0].body)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "joins multiple parts" do
|
|
161
|
+
expect(described_class.new(nil, parts).content).to eq(parts.map(&:body).join("\n"))
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "returns an empty string when no parts" do
|
|
165
|
+
expect(described_class.new(nil, []).content).to eq("")
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Server::Adapters::Afilias do
|
|
6
|
+
let(:definition) { [:tld, ".test", "whois.afilias-grs.info", {}] }
|
|
7
|
+
let(:server) { described_class.new(*definition) }
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
describe "#lookup" do
|
|
11
|
+
context "without referral" do
|
|
12
|
+
it "returns the WHOIS record" do
|
|
13
|
+
response = "No match for example.test."
|
|
14
|
+
expected = response
|
|
15
|
+
expect(server.query_handler).to receive(:call).with("example.test", "whois.afilias-grs.info", 43).and_return(response)
|
|
16
|
+
|
|
17
|
+
record = server.lookup("example.test")
|
|
18
|
+
expect(record.to_s).to eq(expected)
|
|
19
|
+
expect(record.parts.size).to eq(1)
|
|
20
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: response, host: "whois.afilias-grs.info")])
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "with referral" do
|
|
25
|
+
it "follows all referrals" do
|
|
26
|
+
referral = File.read(fixture("referrals/afilias.bz.txt"))
|
|
27
|
+
response = "Match for example.test."
|
|
28
|
+
expected = "#{referral}\n#{response}"
|
|
29
|
+
expect(server.query_handler).to receive(:call).with("example.test", "whois.afilias-grs.info", 43).and_return(referral)
|
|
30
|
+
expect(server.query_handler).to receive(:call).with("example.test", "whois.belizenic.bz", 43).and_return(response)
|
|
31
|
+
|
|
32
|
+
record = server.lookup("example.test")
|
|
33
|
+
expect(record.to_s).to eq(expected)
|
|
34
|
+
expect(record.parts.size).to eq(2)
|
|
35
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: referral, host: "whois.afilias-grs.info"), Whois::Record::Part.new(body: response, host: "whois.belizenic.bz")])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "ignores referral if options[:referral] is false" do
|
|
39
|
+
referral = File.read(fixture("referrals/afilias.bz.txt"))
|
|
40
|
+
server.options[:referral] = false
|
|
41
|
+
expect(server.query_handler).to receive(:call).with("example.test", "whois.afilias-grs.info", 43).and_return(referral)
|
|
42
|
+
expect(server.query_handler).not_to receive(:call).with("example.test", "whois.belizenic.bz", 43)
|
|
43
|
+
|
|
44
|
+
record = server.lookup("example.test")
|
|
45
|
+
expect(record.parts.size).to eq(1)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Server::Adapters::Arin do
|
|
6
|
+
let(:definition) { [:ipv4, "0.0.0.0/1", "whois.arin.net"] }
|
|
7
|
+
let(:server) { described_class.new(*definition) }
|
|
8
|
+
|
|
9
|
+
describe "#lookup" do
|
|
10
|
+
context "without referral" do
|
|
11
|
+
it "returns the WHOIS record" do
|
|
12
|
+
response = "Whois Response"
|
|
13
|
+
expected = response
|
|
14
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(response)
|
|
15
|
+
record = server.lookup("0.0.0.0")
|
|
16
|
+
expect(record.to_s).to eq(expected)
|
|
17
|
+
expect(record.parts.size).to eq(1)
|
|
18
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: response, host: "whois.arin.net")])
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "with referral" do
|
|
23
|
+
it "follows whois:// referrals" do
|
|
24
|
+
referral = File.read(fixture("referrals/arin_referral_whois.txt"))
|
|
25
|
+
response = "Whois Response"
|
|
26
|
+
expected = "#{referral}\n#{response}"
|
|
27
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(referral)
|
|
28
|
+
expect(server.query_handler).to receive(:call).with("0.0.0.0", "whois.ripe.net", 43).and_return(response)
|
|
29
|
+
|
|
30
|
+
record = server.lookup("0.0.0.0")
|
|
31
|
+
expect(record.to_s).to eq(expected)
|
|
32
|
+
expect(record.parts.size).to eq(2)
|
|
33
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: referral, host: "whois.arin.net"),
|
|
34
|
+
Whois::Record::Part.new(body: response, host: "whois.ripe.net"),])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "follows rwhois:// referrals" do
|
|
38
|
+
referral = File.read(fixture("referrals/arin_referral_rwhois.txt"))
|
|
39
|
+
response = "Whois Response"
|
|
40
|
+
expected = "#{referral}\n#{response}"
|
|
41
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(referral)
|
|
42
|
+
expect(server.query_handler).to receive(:call).with("0.0.0.0", "rwhois.servernap.net", 4321).and_return(response)
|
|
43
|
+
|
|
44
|
+
record = server.lookup("0.0.0.0")
|
|
45
|
+
expect(record.to_s).to eq(expected)
|
|
46
|
+
expect(record.parts.size).to eq(2)
|
|
47
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: referral, host: "whois.arin.net"),
|
|
48
|
+
Whois::Record::Part.new(body: response, host: "rwhois.servernap.net"),])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "ignores referral if options[:referral] is false" do
|
|
52
|
+
referral = File.read(fixture("referrals/arin_referral_whois.txt"))
|
|
53
|
+
server.options[:referral] = false
|
|
54
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(referral)
|
|
55
|
+
expect(server.query_handler).not_to receive(:call).with("0.0.0.0", "whois.ripe.net", 43)
|
|
56
|
+
|
|
57
|
+
record = server.lookup("0.0.0.0")
|
|
58
|
+
expect(record.parts.size).to eq(1)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "ignores referral (gracefully) if missing" do
|
|
62
|
+
referral = File.read(fixture("referrals/arin_referral_missing.txt"))
|
|
63
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(referral)
|
|
64
|
+
expect(server.query_handler).not_to receive(:call)
|
|
65
|
+
|
|
66
|
+
record = server.lookup("0.0.0.0")
|
|
67
|
+
expect(record.parts.size).to eq(1)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "folows referrals without ports" do
|
|
71
|
+
referral = File.read(fixture("referrals/arin_referral_apnic.txt"))
|
|
72
|
+
response = "Whois Response"
|
|
73
|
+
expect(server.query_handler).to receive(:call).with("n + 0.0.0.0", "whois.arin.net", 43).and_return(referral)
|
|
74
|
+
expect(server.query_handler).to receive(:call).with("0.0.0.0", "whois.apnic.net", 43).and_return(response)
|
|
75
|
+
|
|
76
|
+
record = server.lookup("0.0.0.0")
|
|
77
|
+
expect(record.parts.size).to eq(2)
|
|
78
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: referral, host: "whois.arin.net"),
|
|
79
|
+
Whois::Record::Part.new(body: response, host: "whois.apnic.net"),])
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "whois/server/adapters/arin"
|
|
5
|
+
|
|
6
|
+
describe Whois::Server::Adapters::Arpa do
|
|
7
|
+
let(:definition) { [:tld, ".in-addr.arpa", nil, {}] }
|
|
8
|
+
|
|
9
|
+
describe "#lookup" do
|
|
10
|
+
it "returns the WHOIS record" do
|
|
11
|
+
server = described_class.new(*definition)
|
|
12
|
+
expect(Whois::Server::Adapters::Arin.query_handler).to receive(:call)
|
|
13
|
+
.with("n + 229.128.in-addr.arpa", "whois.arin.net", 43)
|
|
14
|
+
.and_return(response = "Whois Response")
|
|
15
|
+
|
|
16
|
+
record = server.lookup("229.128.in-addr.arpa")
|
|
17
|
+
expect(record.to_s).to eq(response)
|
|
18
|
+
expect(record.parts).to eq([Whois::Record::Part.new(body: response, host: "whois.arin.net")])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "discards newlines" do
|
|
22
|
+
server = described_class.new(*definition)
|
|
23
|
+
|
|
24
|
+
expect do
|
|
25
|
+
server.lookup("229.128.in-addr.arpa\nextra")
|
|
26
|
+
end.to raise_error(Whois::ServerError, "Invalid .in-addr.arpa address")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe Whois::Server::Adapters::Base do
|
|
6
|
+
let(:definition) { [:tld, ".test", "whois.test", { foo: "bar" }] }
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
describe "#initialize" do
|
|
10
|
+
it "requires type, allocation, and host parameters" do
|
|
11
|
+
expect { described_class.new(:tld) }.to raise_error(ArgumentError)
|
|
12
|
+
expect { described_class.new(:tld, ".test") }.to raise_error(ArgumentError)
|
|
13
|
+
expect { described_class.new(:tld, ".test", "whois.test") }.not_to raise_error
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "accepts an options parameter" do
|
|
17
|
+
expect { described_class.new(:tld, ".test", "whois.test", { foo: "bar" }) }.not_to raise_error
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "sets instance variables from arguments" do
|
|
21
|
+
instance = described_class.new(:tld, ".test", "whois.test", { foo: "bar" })
|
|
22
|
+
expect(instance.type).to eq(:tld)
|
|
23
|
+
expect(instance.allocation).to eq(".test")
|
|
24
|
+
expect(instance.host).to eq("whois.test")
|
|
25
|
+
expect(instance.options).to eq({ foo: "bar" })
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "defaults options to an empty hash" do
|
|
29
|
+
instance = described_class.new(:tld, ".test", "whois.test")
|
|
30
|
+
expect(instance.options).to eq({})
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "#==" do
|
|
35
|
+
it "returns true when other is the same instance" do
|
|
36
|
+
one = two = described_class.new(*definition)
|
|
37
|
+
|
|
38
|
+
expect(one == two).to be_truthy
|
|
39
|
+
expect(one).to eql(two)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "returns true when other has same class and has the same attributes" do
|
|
43
|
+
one = described_class.new(*definition)
|
|
44
|
+
two = described_class.new(*definition)
|
|
45
|
+
|
|
46
|
+
expect(one == two).to be_truthy
|
|
47
|
+
expect(one).to eql(two)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "returns true when other has descendant class and has the same attributes" do
|
|
51
|
+
subklass = Class.new(described_class)
|
|
52
|
+
one = described_class.new(*definition)
|
|
53
|
+
two = subklass.new(*definition)
|
|
54
|
+
|
|
55
|
+
expect(one == two).to be_truthy
|
|
56
|
+
expect(one).to eql(two)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "returns false when other has different class and has the same attributes" do
|
|
60
|
+
one = described_class.new(*definition)
|
|
61
|
+
two = Struct.new(:type, :allocation, :host, :options).new(*definition)
|
|
62
|
+
|
|
63
|
+
expect(one == two).to be_falsey
|
|
64
|
+
expect(one).not_to eql(two)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "returns false when other has different attributes" do
|
|
68
|
+
one = described_class.new(:tld, ".test", "whois.test")
|
|
69
|
+
two = described_class.new(:tld, ".cool", "whois.test")
|
|
70
|
+
|
|
71
|
+
expect(one == two).to be_falsey
|
|
72
|
+
expect(one).not_to eql(two)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "returns false when other has different options" do
|
|
76
|
+
one = described_class.new(:tld, ".test", "whois.test")
|
|
77
|
+
two = described_class.new(:tld, ".test", "whois.test", { foo: "bar" })
|
|
78
|
+
|
|
79
|
+
expect(one == two).to be_falsey
|
|
80
|
+
expect(one).not_to eql(two)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
describe "#configure" do
|
|
86
|
+
it "merges settings with current options" do
|
|
87
|
+
a = described_class.new(:tld, ".test", "whois.test", { hello: "world" })
|
|
88
|
+
a.configure(foo: "bar")
|
|
89
|
+
expect(a.options).to eq({ hello: "world", foo: "bar" })
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "gives higher priority to settings argument" do
|
|
93
|
+
a = described_class.new(:tld, ".test", "whois.test", { foo: "bar" })
|
|
94
|
+
expect(a.options).to eq({ foo: "bar" })
|
|
95
|
+
a.configure(foo: "baz")
|
|
96
|
+
expect(a.options).to eq({ foo: "baz" })
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "overrides @host if :host option exists" do
|
|
100
|
+
a = described_class.new(:tld, ".test", "whois.test", { hello: "world" })
|
|
101
|
+
a.configure(foo: "bar", host: "whois.example.com")
|
|
102
|
+
expect(a.options).to eq({ hello: "world", foo: "bar", host: "whois.example.com" })
|
|
103
|
+
expect(a.host).to eq("whois.example.com")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
describe "#lookup" do
|
|
109
|
+
it "raises NotImplementedError" do
|
|
110
|
+
expect {
|
|
111
|
+
described_class.new(*definition).lookup("example.test")
|
|
112
|
+
}.to raise_error(NotImplementedError)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "#request" do
|
|
117
|
+
it "is an abstract method" do
|
|
118
|
+
expect {
|
|
119
|
+
described_class.new(*definition).request("example.test")
|
|
120
|
+
}.to raise_error(NotImplementedError)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe "#query_the_socket" do
|
|
125
|
+
context "without :bind_host or :bind_port options" do
|
|
126
|
+
let(:server) { described_class.new(:tld, ".test", "whois.test", {}) }
|
|
127
|
+
|
|
128
|
+
it "does not bind the WHOIS query" do
|
|
129
|
+
expect(described_class.query_handler).to receive(:call).with("example.test", "whois.test", 43)
|
|
130
|
+
|
|
131
|
+
server.send(:query_the_socket, "example.test", "whois.test", 43)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context "with :bind_host and :bind_port options" do
|
|
136
|
+
let(:server) { described_class.new(:tld, ".test", "whois.test", { bind_host: "192.168.1.1", bind_port: 3000 }) }
|
|
137
|
+
|
|
138
|
+
it "binds the WHOIS query to given host and port" do
|
|
139
|
+
expect(described_class.query_handler).to receive(:call).with("example.test", "whois.test", 43, "192.168.1.1", 3000)
|
|
140
|
+
|
|
141
|
+
server.send(:query_the_socket, "example.test", "whois.test", 43)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context "with :bind_port and without :bind_host options" do
|
|
146
|
+
let(:server) { described_class.new(:tld, ".test", "whois.test", { bind_port: 3000 }) }
|
|
147
|
+
|
|
148
|
+
it "binds the WHOIS query to given port and defaults host" do
|
|
149
|
+
expect(described_class.query_handler).to receive(:call).with("example.test", "whois.test", 43, described_class::DEFAULT_BIND_HOST, 3000)
|
|
150
|
+
|
|
151
|
+
server.send(:query_the_socket, "example.test", "whois.test", 43)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|