Include hosts resolver in request socket DNS lookup (#38699)

This commit is contained in:
Matt Jankowski 2026-04-17 04:09:37 -04:00 committed by GitHub
parent 3c88310f37
commit d5f0e37260
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 26 deletions

View File

@ -292,11 +292,9 @@ class Request
begin
addresses = [IPAddr.new(host)]
rescue IPAddr::InvalidAddressError
Resolv::DNS.open do |dns|
dns.timeouts = 5
addresses = dns.getaddresses(host)
addresses = addresses.grep(Resolv::IPv6).take(2) + addresses.grep_v(Resolv::IPv6).take(2)
end
resolvers = [Resolv::Hosts.new, Resolv::DNS.new.tap { |dns| dns.timeouts = 5 }]
addresses = Resolv.new(resolvers).getaddresses(host)
addresses = addresses.grep(Resolv::IPv6::Regex).take(2) + addresses.grep_v(Resolv::IPv6::Regex).take(2)
end
socks = []

View File

@ -86,14 +86,16 @@ RSpec.describe Fasp::Request do
WebMock.enable!
end
let(:resolv_service) { instance_double(Resolv) }
before do
allow(Resolv).to receive(:new).and_return(resolv_service)
allow(resolv_service).to receive(:getaddresses).with('reqprov.example.com').and_return(%w(0.0.0.0 2001:db8::face))
end
it 'raises Mastodon::ValidationError' do
resolver = instance_double(Resolv::DNS)
allow(resolver).to receive(:getaddresses).with('reqprov.example.com').and_return(%w(0.0.0.0 2001:db8::face))
allow(resolver).to receive(:timeouts=).and_return(nil)
allow(Resolv::DNS).to receive(:open).and_yield(resolver)
expect { subject.send(method, '/test_path') }.to raise_error(Mastodon::ValidationError)
expect { subject.send(method, '/test_path') }
.to raise_error(Mastodon::ValidationError)
end
end
end

View File

@ -66,15 +66,20 @@ RSpec.describe Request do
expect(a_request(:get, 'http://example.com')).to have_been_made.once
end
it 'executes a HTTP request when the first address is private' do
resolver = instance_double(Resolv::DNS)
context 'when first address is private' do
let(:resolv_service) { instance_double(Resolv) }
allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:4860:4860::8844))
allow(resolver).to receive(:timeouts=).and_return(nil)
allow(Resolv::DNS).to receive(:open).and_yield(resolver)
before do
allow(Resolv).to receive(:new).and_return(resolv_service)
allow(resolv_service).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:4860:4860::8844))
end
expect { |block| subject.perform(&block) }.to yield_control
expect(a_request(:get, 'http://example.com')).to have_been_made.once
it 'executes a HTTP request' do
expect { |block| subject.perform(&block) }
.to yield_control
expect(a_request(:get, 'http://example.com'))
.to have_been_made.once
end
end
it 'makes a request with expected headers, yields, and closes the underlying connection' do
@ -123,14 +128,16 @@ RSpec.describe Request do
WebMock.enable!
end
let(:resolv_service) { instance_double(Resolv) }
before do
allow(Resolv).to receive(:new).with([be_a(Resolv::Hosts), be_a(Resolv::DNS)]).and_return(resolv_service)
allow(resolv_service).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:db8::face))
end
it 'raises Mastodon::ValidationError' do
resolver = instance_double(Resolv::DNS)
allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:db8::face))
allow(resolver).to receive(:timeouts=).and_return(nil)
allow(Resolv::DNS).to receive(:open).and_yield(resolver)
expect { subject.perform }.to raise_error Mastodon::ValidationError
expect { subject.perform }
.to raise_error Mastodon::ValidationError
end
end