diff --git a/ChangeLog b/ChangeLog index b9207b80fa..ce9949878a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Wed Oct 6 12:28:22 2010 Tanaka Akira + + * lib/uri/generic.rb (URI::Generic#hostname): new method. + (URI::Generic#hostname=): ditto. + + * lib/open-uri.rb: use URI#hostname + + * lib/net/http.rb: ditto. + + [ruby-core:32056] + Wed Oct 6 11:52:12 2010 Nobuyoshi Nakada * io.c (fptr_finalize): write_mutex might have been destroyed diff --git a/lib/net/http.rb b/lib/net/http.rb index 920301f350..0ae1ba8c8f 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -64,7 +64,7 @@ module Net #:nodoc: # require 'uri' # # url = URI.parse('http://www.example.com/index.html') - # res = Net::HTTP.start(url.host, url.port) {|http| + # res = Net::HTTP.start(url.hostname, url.port) {|http| # http.get('/index.html') # } # puts res.body @@ -75,7 +75,7 @@ module Net #:nodoc: # # url = URI.parse('http://www.example.com/index.html') # req = Net::HTTP::Get.new(url.path) - # res = Net::HTTP.start(url.host, url.port) {|http| + # res = Net::HTTP.start(url.hostname, url.port) {|http| # http.request(req) # } # puts res.body @@ -101,7 +101,7 @@ module Net #:nodoc: # req = Net::HTTP::Post.new(url.path) # req.basic_auth 'jack', 'pass' # req.set_form_data({'from' => '2005-01-01', 'to' => '2005-03-31'}, ';') - # res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) } + # res = Net::HTTP.new(url.hostname, url.port).start {|http| http.request(req) } # case res # when Net::HTTPSuccess, Net::HTTPRedirection # # OK @@ -390,7 +390,7 @@ module Net #:nodoc: } else uri = uri_or_host - new(uri.host, uri.port).start {|http| + new(uri.hostname, uri.port).start {|http| return http.request_get(uri.request_uri, &block) } end @@ -415,7 +415,7 @@ module Net #:nodoc: req = Post.new(url.path) req.form_data = params req.basic_auth url.user, url.password if url.user - new(url.host, url.port).start {|http| + new(url.hostname, url.port).start {|http| http.request(req) } end diff --git a/lib/open-uri.rb b/lib/open-uri.rb index bb45d63ae6..6706068300 100644 --- a/lib/open-uri.rb +++ b/lib/open-uri.rb @@ -263,17 +263,17 @@ module OpenURI # HTTP or HTTPS if proxy if proxy_user && proxy_pass - klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass) + klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port, proxy_user, proxy_pass) else - klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port) + klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port) end end - target_host = target.host + target_host = target.hostname target_port = target.port request_uri = target.request_uri else # FTP over HTTP proxy - target_host = proxy_uri.host + target_host = proxy_uri.hostname target_port = proxy_uri.port request_uri = target.to_s if proxy_user && proxy_pass @@ -736,10 +736,10 @@ module URI proxy_uri = ENV[name] || ENV[name.upcase] end - if proxy_uri && self.host + if proxy_uri && self.hostname require 'socket' begin - addr = IPSocket.getaddress(self.host) + addr = IPSocket.getaddress(self.hostname) proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr rescue SocketError end @@ -804,7 +804,7 @@ module URI # The access sequence is defined by RFC 1738 ftp = Net::FTP.new - ftp.connect(self.host, self.port) + ftp.connect(self.hostname, self.port) ftp.passive = true if !options[:ftp_active_mode] # todo: extract user/passwd from .netrc. user = 'anonymous' diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index f20b2d26e1..f8354e1835 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -205,8 +205,31 @@ module URI self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2) self.set_port(self.default_port) if self.default_port && !@port end + attr_reader :scheme + + # returns the host component of the URI. + # + # URI("http://foo/bar/baz").host #=> "foo" + # + # It returns nil if no host component. + # + # URI("mailto:foo@example.org").host #=> nil + # + # The component doesn't contains the port number. + # + # URI("http://foo:8080/bar/baz").host #=> "foo" + # + # Since IPv6 addresses are wrapped by brackets in URIs, + # this method returns IPv6 addresses wrapped by brackets. + # This form is not appropriate to pass socket methods such as TCPSocket.open. + # If unwrapped host names are required, use "hostname" method. + # + # URI("http://[::1]/bar/baz").host #=> "[::1]" + # URI("http://[::1]/bar/baz").hostname #=> "::1" + # attr_reader :host + attr_reader :port attr_reader :registry attr_reader :path @@ -412,6 +435,38 @@ module URI v end + # extract the host part of the URI and unwrap brackets for IPv6 addresses. + # + # This method is same as URI::Generic#host except + # brackets for IPv6 (andn future IP) addresses are removed. + # + # u = URI("http://[::1]/bar") + # p u.hostname #=> "::1" + # p u.host #=> "[::1]" + # + def hostname + v = self.host + /\A\[(.*)\]\z/ =~ v ? $1 : v + end + + # set the host part of the URI as the argument with brackets for IPv6 addresses. + # + # This method is same as URI::Generic#host= except + # the argument can be bare IPv6 address. + # + # u = URI("http://foo/bar") + # p u.to_s #=> "http://foo/bar" + # u.hostname = "::1" + # p u.to_s #=> "http://[::1]/bar" + # + # If the arugument seems IPv6 address, + # it is wrapped by brackets. + # + def hostname=(v) + v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v + self.host = v + end + def check_port(v) return v unless v diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb index fcaa599724..821b147fa0 100644 --- a/test/uri/test_generic.rb +++ b/test/uri/test_generic.rb @@ -695,4 +695,14 @@ class URI::TestGeneric < Test::Unit::TestCase assert_raise(URI::InvalidURIError) { uri.path = 'bar' } assert_raise(URI::InvalidURIError) { uri.query = 'bar' } end + + def test_ipv6 + assert_equal("[::1]", URI("http://[::1]/bar/baz").host) + assert_equal("::1", URI("http://[::1]/bar/baz").hostname) + + u = URI("http://foo/bar") + assert_equal("http://foo/bar", u.to_s) + u.hostname = "::1" + assert_equal("http://[::1]/bar", u.to_s) + end end