From 0b0c96c4f02f5fb579ca71b5cc6da5779e211b62 Mon Sep 17 00:00:00 2001 From: 0x1eef <0x1eef@protonmail.com> Date: Tue, 19 Sep 2023 03:36:44 -0300 Subject: [PATCH] Add support for URI that contains an IPv6 address Fix #73: Net::HTTP.get_response(URI.parse("http://[::1]")) When the 'Host' header does not wrap an IPv6 address in brackets, some servers (eg Apache) reject the request with a 400 status code. --- lib/net/http/generic_request.rb | 8 ++++---- test/net/http/test_http_request.rb | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb index 44e329a0..8f07c8f0 100644 --- a/lib/net/http/generic_request.rb +++ b/lib/net/http/generic_request.rb @@ -19,10 +19,10 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc: if URI === uri_or_path then raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path - hostname = uri_or_path.hostname - raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0) + host = uri_or_path.host + raise ArgumentError, "no host component for URI" unless (host && host.length > 0) @uri = uri_or_path.dup - host = @uri.hostname.dup + host = host.dup host << ":" << @uri.port.to_s if @uri.port != @uri.default_port @path = uri_or_path.request_uri raise ArgumentError, "no HTTP request path given" unless @path @@ -220,7 +220,7 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only end if host = self['host'] - host.sub!(/:.*/m, '') + host.sub!(/:\d+\Z/, '') elsif host = @uri.host else host = addr diff --git a/test/net/http/test_http_request.rb b/test/net/http/test_http_request.rb index 7fd82b03..bd6242b8 100644 --- a/test/net/http/test_http_request.rb +++ b/test/net/http/test_http_request.rb @@ -89,5 +89,27 @@ def test_header_set 'Bug #7831 - do not decode content if the user overrides' end if Net::HTTP::HAVE_ZLIB + def test_ipv6_address_as_host_header + req = Net::HTTP::Get.new(URI.parse("http://[::1]")) + assert_equal "[::1]", req['host'] + end + + def test_ipv6_address_as_host_header_with_port + req = Net::HTTP::Get.new(URI.parse("http://[::1]:2020")) + assert_equal "[::1]:2020", req['host'] + end + + def test_ipv6_address_on_update_uri + req = Net::HTTP::Get.new(URI.parse("http://[::1]")) + req.send(:update_uri, "[::1]", 80, false) + assert_equal "[::1]", req.instance_variable_get(:@uri).host + end + + def test_ipv6_address_with_port_on_update_uri + req = Net::HTTP::Get.new(URI.parse("http://[::1]:7777")) + req.send(:update_uri, "[::1]", 2020, false) + assert_equal "[::1]", req.instance_variable_get(:@uri).host + assert_equal 2020, req.instance_variable_get(:@uri).port + end end