Skip to content

Commit

Permalink
Merge pull request #933 from JohannaHartmann/jh/fix-issue-806
Browse files Browse the repository at this point in the history
Fix: Handle IPv6 hostname correctly (closes #806)
  • Loading branch information
bblimke authored Mar 5, 2021
2 parents 6e3de61 + fe6e7d7 commit 79e60c9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
13 changes: 10 additions & 3 deletions lib/webmock/http_lib_adapters/net_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,6 @@ module WebMock
module NetHTTPUtility

def self.request_signature_from_request(net_http, request, body = nil)
protocol = net_http.use_ssl? ? "https" : "http"

path = request.path

if path.respond_to?(:request_uri) #https://github.com/bblimke/webmock/issues/288
Expand All @@ -323,7 +321,7 @@ def self.request_signature_from_request(net_http, request, body = nil)

path = WebMock::Util::URI.heuristic_parse(path).request_uri if path =~ /^http/

uri = "#{protocol}://#{net_http.address}:#{net_http.port}#{path}"
uri = get_uri(net_http, path)
method = request.method.downcase.to_sym

headers = Hash[*request.to_hash.map {|k,v| [k, v]}.inject([]) {|r,x| r + x}]
Expand All @@ -343,6 +341,15 @@ def self.request_signature_from_request(net_http, request, body = nil)
WebMock::RequestSignature.new(method, uri, body: request.body, headers: headers)
end

def self.get_uri(net_http, path)
protocol = net_http.use_ssl? ? "https" : "http"

hostname = net_http.address
hostname = "[#{hostname}]" if /\A\[.*\]\z/ !~ hostname && /:/ =~ hostname

"#{protocol}://#{hostname}:#{net_http.port}#{path}"
end

def self.validate_headers(headers)
# For Ruby versions < 2.3.0, if you make a request with headers that are symbols
# Net::HTTP raises a NoMethodError
Expand Down
42 changes: 42 additions & 0 deletions spec/acceptance/net_http/net_http_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,46 @@ def perform_get_with_returning_block
http.request(req, '')
end
end

describe "hostname handling" do
it "should set brackets around the hostname if it is an IPv6 address" do
net_http = Net::HTTP.new('b2dc:5bdf:4f0d::3014:e0ca', 80)
path = '/example.jpg'
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
end

it "should not set brackets around the hostname if it is already wrapped by brackets" do
net_http = Net::HTTP.new('[b2dc:5bdf:4f0d::3014:e0ca]', 80)
path = '/example.jpg'
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://[b2dc:5bdf:4f0d::3014:e0ca]:80/example.jpg')
end

it "should not set brackets around the hostname if it is an IPv4 address" do
net_http = Net::HTTP.new('181.152.137.168', 80)
path = '/example.jpg'
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://181.152.137.168:80/example.jpg')
end

it "should not set brackets around the hostname if it is a domain" do
net_http = Net::HTTP.new('www.example.com', 80)
path = '/example.jpg'
expect(WebMock::NetHTTPUtility.get_uri(net_http, path)).to eq('http://www.example.com:80/example.jpg')
end

it 'should work with IPv6 addresses' do
WebMock.stub_request(:get, 'http://[b2dc:5bdf:4f0d::3014:e0c1]:80/example.jpg')
uri = URI.parse('http://[b2dc:5bdf:4f0d::3014:e0c1]:80/example.jpg')
request = Net::HTTP::Get.new(uri)

expect { Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(request) } }.not_to raise_error
end

it 'should work with IPv4 addresses' do
WebMock.stub_request(:get, 'http://181.152.137.168:80/example.jpg')
uri = URI.parse('http://181.152.137.168:80/example.jpg')
request = Net::HTTP::Get.new(uri)

expect { Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(request) } }.not_to raise_error
end
end
end

0 comments on commit 79e60c9

Please sign in to comment.