summaryrefslogtreecommitdiff
path: root/lib/uri/generic.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/uri/generic.rb')
-rw-r--r--lib/uri/generic.rb863
1 files changed, 390 insertions, 473 deletions
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index b1195fdf0b..6a0f638d76 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -1,13 +1,16 @@
+# frozen_string_literal: true
+
# = uri/generic.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
-require 'uri/common'
+require_relative 'common'
+autoload :IPSocket, 'socket'
+autoload :IPAddr, 'ipaddr'
module URI
@@ -19,26 +22,26 @@ module URI
include URI
#
- # A Default port of nil for URI::Generic
+ # A Default port of nil for URI::Generic.
#
DEFAULT_PORT = nil
#
- # Returns default port
+ # Returns default port.
#
def self.default_port
self::DEFAULT_PORT
end
#
- # Returns default port
+ # Returns default port.
#
def default_port
self.class.default_port
end
#
- # An Array of the available components for URI::Generic
+ # An Array of the available components for URI::Generic.
#
COMPONENT = [
:scheme,
@@ -55,30 +58,22 @@ module URI
self::COMPONENT
end
- #
- # Default to not use the registry for a URI::Generic
- #
- USE_REGISTRY = false
+ USE_REGISTRY = false # :nodoc:
- #
- # Returns whether a registry of naming
- # authorities are being used.
- #
- def self.use_registry
+ def self.use_registry # :nodoc:
self::USE_REGISTRY
end
#
# == Synopsis
#
- # See #new
+ # See ::new.
#
# == Description
#
# At first, tries to create a new URI::Generic instance using
# URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
- # then it URI::Escape.escape all URI components and tries again.
- #
+ # then it does URI::RFC2396_PARSER.escape all URI components and tries again.
#
def self.build2(args)
begin
@@ -87,7 +82,7 @@ module URI
if args.kind_of?(Array)
return self.build(args.collect{|x|
if x.is_a?(String)
- DEFAULT_PARSER.escape(x)
+ URI::RFC2396_PARSER.escape(x)
else
x
end
@@ -96,7 +91,7 @@ module URI
tmp = {}
args.each do |key, value|
tmp[key] = if value
- DEFAULT_PARSER.escape(value)
+ URI::RFC2396_PARSER.escape(value)
else
value
end
@@ -109,14 +104,14 @@ module URI
#
# == Synopsis
#
- # See #new
+ # See ::new.
#
# == Description
#
# Creates a new URI::Generic instance from components of URI::Generic
# with check. Components are: scheme, userinfo, host, port, registry, path,
- # opaque, query and fragment. You can provide arguments either by an Array or a Hash.
- # See #new for hash keys to use or for order of array items.
+ # opaque, query, and fragment. You can provide arguments either by an Array or a Hash.
+ # See ::new for hash keys to use or for order of array items.
#
def self.build(args)
if args.kind_of?(Array) &&
@@ -131,40 +126,41 @@ module URI
end
end
else
- component = self.class.component rescue ::URI::Generic::COMPONENT
+ component = self.component rescue ::URI::Generic::COMPONENT
raise ArgumentError,
- "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
+ "expected Array of or Hash of components of #{self} (#{component.join(', ')})"
end
tmp << nil
tmp << true
return self.new(*tmp)
end
+
#
# == Args
#
# +scheme+::
# Protocol scheme, i.e. 'http','ftp','mailto' and so on.
# +userinfo+::
- # User name and password, i.e. 'sdmitry:bla'
+ # User name and password, i.e. 'sdmitry:bla'.
# +host+::
- # Server host name
+ # Server host name.
# +port+::
- # Server port
+ # Server port.
# +registry+::
# Registry of naming authorities.
# +path+::
- # Path on server
+ # Path on server.
# +opaque+::
- # Opaque part
+ # Opaque part.
# +query+::
- # Query data
+ # Query data.
# +fragment+::
- # A part of URI after '#' sign
+ # Part of the URI after '#' character.
# +parser+::
- # Parser for internal use [URI::DEFAULT_PARSER by default]
+ # Parser for internal use [URI::DEFAULT_PARSER by default].
# +arg_check+::
- # Check arguments [false by default]
+ # Check arguments [false by default].
#
# == Description
#
@@ -185,115 +181,110 @@ module URI
@path = nil
@query = nil
@opaque = nil
- @registry = nil
@fragment = nil
@parser = parser == DEFAULT_PARSER ? nil : parser
if arg_check
self.scheme = scheme
- self.userinfo = userinfo
- self.host = host
+ self.hostname = host
self.port = port
+ self.userinfo = userinfo
self.path = path
self.query = query
self.opaque = opaque
- self.registry = registry
self.fragment = fragment
else
self.set_scheme(scheme)
- self.set_userinfo(userinfo)
self.set_host(host)
self.set_port(port)
+ self.set_userinfo(userinfo)
self.set_path(path)
- self.set_query(query)
+ self.query = query
self.set_opaque(opaque)
- self.set_registry(registry)
- self.set_fragment(fragment)
+ self.fragment=(fragment)
end
- if @registry && !self.class.use_registry
+ if registry
raise InvalidURIError,
- "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
+ "the scheme #{@scheme} does not accept registry part: #{registry} (or bad hostname?)"
end
- @scheme.freeze if @scheme
+ @scheme&.freeze
self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
self.set_port(self.default_port) if self.default_port && !@port
end
#
- # returns the scheme component of the URI.
+ # Returns the scheme component of the URI.
#
# URI("http://foo/bar/baz").scheme #=> "http"
#
attr_reader :scheme
- # returns the host component of the URI.
+ # Returns the host component of the URI.
#
# URI("http://foo/bar/baz").host #=> "foo"
#
- # It returns nil if no host component.
+ # It returns nil if no host component exists.
#
# URI("mailto:foo@example.org").host #=> nil
#
- # The component doesn't contains the port number.
+ # The component does not contain 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.
+ # Since IPv6 addresses are wrapped with brackets in URIs,
+ # this method returns IPv6 addresses wrapped with brackets.
+ # This form is not appropriate to pass to socket methods such as TCPSocket.open.
+ # If unwrapped host names are required, use the #hostname method.
#
- # URI("http://[::1]/bar/baz").host #=> "[::1]"
+ # URI("http://[::1]/bar/baz").host #=> "[::1]"
# URI("http://[::1]/bar/baz").hostname #=> "::1"
#
attr_reader :host
- # returns the port component of the URI.
- #
- # URI("http://foo/bar/baz").port #=> "80"
+ # Returns the port component of the URI.
#
- # URI("http://foo:8080/bar/baz").port #=> "8080"
+ # URI("http://foo/bar/baz").port #=> 80
+ # URI("http://foo:8080/bar/baz").port #=> 8080
#
attr_reader :port
- # returns the registry component of the URI.
- #
- # (see RFC2396 Section 3.2)
- #
- attr_reader :registry
+ def registry # :nodoc:
+ nil
+ end
- # returns the path component of the URI.
+ # Returns the path component of the URI.
#
# URI("http://foo/bar/baz").path #=> "/bar/baz"
#
attr_reader :path
- # returns the query component of the URI.
+ # Returns the query component of the URI.
#
# URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar"
#
attr_reader :query
- # returns the opaque part of the URI.
+ # Returns the opaque part of the URI.
#
# URI("mailto:foo@example.org").opaque #=> "foo@example.org"
+ # URI("http://foo/bar/baz").opaque #=> nil
#
- # Portion of the path that does make use of the slash '/'.
- # The path typically refers to the absolute path and the opaque part.
- # (see RFC2396 Section 3 and 5.2)
+ # The portion of the path that does not make use of the slash '/'.
+ # The path typically refers to an absolute path or an opaque part.
+ # (See RFC2396 Section 3 and 5.2.)
#
attr_reader :opaque
- # returns the fragment component of the URI.
+ # Returns the fragment component of the URI.
#
# URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies"
#
attr_reader :fragment
- # returns the parser to be used.
+ # Returns the parser to be used.
#
- # Unless a URI::Parser is defined, then DEFAULT_PARSER is used.
+ # Unless the +parser+ is defined, DEFAULT_PARSER is used.
#
def parser
if !defined?(@parser) || !@parser
@@ -303,7 +294,8 @@ module URI
end
end
- # replace self by other URI object
+ # Replaces self by other URI object.
+ #
def replace!(oth)
if self.class != oth.class
raise ArgumentError, "expected #{self.class} object"
@@ -323,7 +315,7 @@ module URI
end
#
- # check the scheme +v+ component against the URI::Parser Regexp for :SCHEME
+ # Checks the scheme +v+ component against the +parser+ Regexp for :SCHEME.
#
def check_scheme(v)
if v && parser.regexp[:SCHEME] !~ v
@@ -335,12 +327,12 @@ module URI
end
private :check_scheme
- # protected setter for the scheme component +v+
+ # Protected setter for the scheme component +v+.
#
- # see also URI::Generic.scheme=
+ # See also URI::Generic.scheme=.
#
def set_scheme(v)
- @scheme = v ? v.downcase : v
+ @scheme = v&.downcase
end
protected :set_scheme
@@ -352,10 +344,10 @@ module URI
#
# == Description
#
- # public setter for the scheme component +v+.
- # (with validation)
+ # Public setter for the scheme component +v+
+ # (with validation).
#
- # see also URI::Generic.check_scheme
+ # See also URI::Generic.check_scheme.
#
# == Usage
#
@@ -363,9 +355,7 @@ module URI
#
# uri = URI.parse("http://my.example.com")
# uri.scheme = "https"
- # # => "https"
- # uri
- # #=> #<URI::HTTP:0x000000008e89e8 URL:https://my.example.com>
+ # uri.to_s #=> "https://my.example.com"
#
def scheme=(v)
check_scheme(v)
@@ -374,13 +364,13 @@ module URI
end
#
- # check the +user+ and +password+.
+ # Checks the +user+ and +password+.
#
# If +password+ is not provided, then +user+ is
# split, using URI::Generic.split_userinfo, to
# pull +user+ and +password.
#
- # see also URI::Generic.check_user, URI::Generic.check_password
+ # See also URI::Generic.check_user, URI::Generic.check_password.
#
def check_userinfo(user, password = nil)
if !password
@@ -394,16 +384,16 @@ module URI
private :check_userinfo
#
- # check the user +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :USERINFO
+ # Checks the user +v+ component for RFC2396 compliance
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
#
def check_user(v)
- if @registry || @opaque
+ if @opaque
raise InvalidURIError,
- "can not set user with registry or opaque"
+ "cannot set user with opaque"
end
return v unless v
@@ -418,16 +408,16 @@ module URI
private :check_user
#
- # check the password +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :USERINFO
+ # Checks the password +v+ component for RFC2396 compliance
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
#
def check_password(v, user = @user)
- if @registry || @opaque
+ if @opaque
raise InvalidURIError,
- "can not set password with registry or opaque"
+ "cannot set password with opaque"
end
return v unless v
@@ -438,7 +428,7 @@ module URI
if parser.regexp[:USERINFO] !~ v
raise InvalidComponentError,
- "bad component(expected user component): #{v}"
+ "bad password component"
end
return true
@@ -446,7 +436,7 @@ module URI
private :check_password
#
- # Sets userinfo, argument is string like 'name:pass'
+ # Sets userinfo, argument is string like 'name:pass'.
#
def userinfo=(userinfo)
if userinfo.nil?
@@ -465,10 +455,10 @@ module URI
#
# == Description
#
- # public setter for the +user+ component.
- # (with validation)
+ # Public setter for the +user+ component
+ # (with validation).
#
- # see also URI::Generic.check_user
+ # See also URI::Generic.check_user.
#
# == Usage
#
@@ -476,9 +466,7 @@ module URI
#
# uri = URI.parse("http://john:S3nsit1ve@my.example.com")
# uri.user = "sam"
- # # => "sam"
- # uri
- # #=> #<URI::HTTP:0x00000000881d90 URL:http://sam:V3ry_S3nsit1ve@my.example.com>
+ # uri.to_s #=> "http://sam@my.example.com"
#
def user=(user)
check_user(user)
@@ -494,10 +482,10 @@ module URI
#
# == Description
#
- # public setter for the +password+ component.
- # (with validation)
+ # Public setter for the +password+ component
+ # (with validation).
#
- # see also URI::Generic.check_password
+ # See also URI::Generic.check_password.
#
# == Usage
#
@@ -505,9 +493,7 @@ module URI
#
# uri = URI.parse("http://john:S3nsit1ve@my.example.com")
# uri.password = "V3ry_S3nsit1ve"
- # # => "V3ry_S3nsit1ve"
- # uri
- # #=> #<URI::HTTP:0x00000000881d90 URL:http://john:V3ry_S3nsit1ve@my.example.com>
+ # uri.to_s #=> "http://john:V3ry_S3nsit1ve@my.example.com"
#
def password=(password)
check_password(password)
@@ -515,35 +501,35 @@ module URI
# returns password
end
- # protect setter for the +user+ component, and +password+ if available.
- # (with validation)
+ # Protected setter for the +user+ component, and +password+ if available
+ # (with validation).
#
- # see also URI::Generic.userinfo=
+ # See also URI::Generic.userinfo=.
#
def set_userinfo(user, password = nil)
unless password
user, password = split_userinfo(user)
end
@user = user
- @password = password if password
+ @password = password
[@user, @password]
end
protected :set_userinfo
- # protected setter for the user component +v+
+ # Protected setter for the user component +v+.
#
- # see also URI::Generic.user=
+ # See also URI::Generic.user=.
#
def set_user(v)
- set_userinfo(v, @password)
+ set_userinfo(v, nil)
v
end
protected :set_user
- # protected setter for the password component +v+
+ # Protected setter for the password component +v+.
#
- # see also URI::Generic.password=
+ # See also URI::Generic.password=.
#
def set_password(v)
@password = v
@@ -551,23 +537,23 @@ module URI
end
protected :set_password
- # returns the userinfo +ui+ as user, password
- # if properly formated as 'user:password'
+ # Returns the userinfo +ui+ as <code>[user, password]</code>
+ # if properly formatted as 'user:password'.
def split_userinfo(ui)
return nil, nil unless ui
- user, password = ui.split(/:/, 2)
+ user, password = ui.split(':', 2)
return user, password
end
private :split_userinfo
- # escapes 'user:password' +v+ based on RFC 1738 section 3.1
+ # Escapes 'user:password' +v+ based on RFC 1738 section 3.1.
def escape_userpass(v)
- v = parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
+ parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
end
private :escape_userpass
- # returns the userinfo, either as 'user' or 'user:password'
+ # Returns the userinfo, either as 'user' or 'user:password'.
def userinfo
if @user.nil?
nil
@@ -578,19 +564,35 @@ module URI
end
end
- # returns the user component
+ # Returns the user component (without URI decoding).
def user
@user
end
- # returns the password component
+ # Returns the password component (without URI decoding).
def password
@password
end
+ # Returns the authority info (array of user, password, host and
+ # port), if any is set. Or returns +nil+.
+ def authority
+ return @user, @password, @host, @port if @user || @password || @host || @port
+ end
+
+ # Returns the user component after URI decoding.
+ def decoded_user
+ URI.decode_uri_component(@user) if @user
+ end
+
+ # Returns the password component after URI decoding.
+ def decoded_password
+ URI.decode_uri_component(@password) if @password
+ end
+
#
- # check the host +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :HOST
+ # Checks the host +v+ component for RFC2396 compliance
+ # and against the +parser+ Regexp for :HOST.
#
# Can not have a registry or opaque component defined,
# with a host component defined.
@@ -598,9 +600,9 @@ module URI
def check_host(v)
return v unless v
- if @registry || @opaque
+ if @opaque
raise InvalidURIError,
- "can not set host with registry or opaque"
+ "cannot set host with registry or opaque"
elsif parser.regexp[:HOST] !~ v
raise InvalidComponentError,
"bad component(expected host component): #{v}"
@@ -610,15 +612,22 @@ module URI
end
private :check_host
- # protected setter for the host component +v+
+ # Protected setter for the host component +v+.
#
- # see also URI::Generic.host=
+ # See also URI::Generic.host=.
#
def set_host(v)
@host = v
end
protected :set_host
+ # Protected setter for the authority info (+user+, +password+, +host+
+ # and +port+). If +port+ is +nil+, +default_port+ will be set.
+ #
+ protected def set_authority(user, password, host, port = nil)
+ @user, @password, @host, @port = user, password, host, port || self.default_port
+ end
+
#
# == Args
#
@@ -627,10 +636,10 @@ module URI
#
# == Description
#
- # public setter for the host component +v+.
- # (with validation)
+ # Public setter for the host component +v+
+ # (with validation).
#
- # see also URI::Generic.check_host
+ # See also URI::Generic.check_host.
#
# == Usage
#
@@ -638,51 +647,49 @@ module URI
#
# uri = URI.parse("http://my.example.com")
# uri.host = "foo.com"
- # # => "foo.com"
- # uri
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://foo.com>
+ # uri.to_s #=> "http://foo.com"
#
def host=(v)
check_host(v)
set_host(v)
+ set_userinfo(nil)
v
end
- # extract the host part of the URI and unwrap brackets for IPv6 addresses.
+ # 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.
+ # This method is the same as URI::Generic#host except
+ # brackets for IPv6 (and future IP) addresses are removed.
#
- # u = URI("http://[::1]/bar")
- # p u.hostname #=> "::1"
- # p u.host #=> "[::1]"
+ # uri = URI("http://[::1]/bar")
+ # uri.hostname #=> "::1"
+ # uri.host #=> "[::1]"
#
def hostname
v = self.host
- /\A\[(.*)\]\z/ =~ v ? $1 : v
+ v&.start_with?('[') && v.end_with?(']') ? v[1..-2] : v
end
- # set the host part of the URI as the argument with brackets for IPv6 addresses.
+ # Sets 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.
+ # This method is the same as URI::Generic#host= except
+ # the argument can be a 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"
+ # uri = URI("http://foo/bar")
+ # uri.hostname = "::1"
+ # uri.to_s #=> "http://[::1]/bar"
#
- # If the arugument seems IPv6 address,
- # it is wrapped by brackets.
+ # If the argument seems to be an IPv6 address,
+ # it is wrapped with brackets.
#
def hostname=(v)
- v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v
+ v = "[#{v}]" if !(v&.start_with?('[') && v&.end_with?(']')) && v&.index(':')
self.host = v
end
#
- # check the port +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :PORT
+ # Checks the port +v+ component for RFC2396 compliance
+ # and against the +parser+ Regexp for :PORT.
#
# Can not have a registry or opaque component defined,
# with a port component defined.
@@ -690,30 +697,24 @@ module URI
def check_port(v)
return v unless v
- if @registry || @opaque
+ if @opaque
raise InvalidURIError,
- "can not set port with registry or opaque"
- elsif !v.kind_of?(Fixnum) && parser.regexp[:PORT] !~ v
+ "cannot set port with registry or opaque"
+ elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v
raise InvalidComponentError,
- "bad component(expected port component): #{v}"
+ "bad component(expected port component): #{v.inspect}"
end
return true
end
private :check_port
- # protected setter for the port component +v+
+ # Protected setter for the port component +v+.
#
- # see also URI::Generic.port=
+ # See also URI::Generic.port=.
#
def set_port(v)
- unless !v || v.kind_of?(Fixnum)
- if v.empty?
- v = nil
- else
- v = v.to_i
- end
- end
+ v = v.empty? ? nil : v.to_i unless !v || v.kind_of?(Integer)
@port = v
end
protected :set_port
@@ -726,10 +727,10 @@ module URI
#
# == Description
#
- # public setter for the port component +v+.
- # (with validation)
+ # Public setter for the port component +v+
+ # (with validation).
#
- # see also URI::Generic.check_port
+ # See also URI::Generic.check_port.
#
# == Usage
#
@@ -737,73 +738,33 @@ module URI
#
# uri = URI.parse("http://my.example.com")
# uri.port = 8080
- # # => 8080
- # uri
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com:8080>
+ # uri.to_s #=> "http://my.example.com:8080"
#
def port=(v)
check_port(v)
set_port(v)
+ set_userinfo(nil)
port
end
- #
- # check the registry +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :REGISTRY
- #
- # Can not have a host, port or user component defined,
- # with a registry component defined.
- #
- def check_registry(v)
- return v unless v
-
- # raise if both server and registry are not nil, because:
- # authority = server | reg_name
- # server = [ [ userinfo "@" ] hostport ]
- if @host || @port || @user # userinfo = @user + ':' + @password
- raise InvalidURIError,
- "can not set registry with host, port, or userinfo"
- elsif v && parser.regexp[:REGISTRY] !~ v
- raise InvalidComponentError,
- "bad component(expected registry component): #{v}"
- end
-
- return true
+ def check_registry(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
private :check_registry
- # protected setter for the registry component +v+
- #
- # see also URI::Generic.registry=
- #
- def set_registry(v)
- @registry = v
+ def set_registry(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
protected :set_registry
- #
- # == Args
- #
- # +v+::
- # String
- #
- # == Description
- #
- # public setter for the registry component +v+.
- # (with validation)
- #
- # see also URI::Generic.check_registry
- #
- def registry=(v)
- check_registry(v)
- set_registry(v)
- v
+ def registry=(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
#
- # check the path +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp
- # for :ABS_PATH and :REL_PATH
+ # Checks the path +v+ component for RFC2396 compliance
+ # and against the +parser+ Regexp
+ # for :ABS_PATH and :REL_PATH.
#
# Can not have a opaque component defined,
# with a path component defined.
@@ -825,7 +786,8 @@ module URI
"bad component(expected absolute path component): #{v}"
end
else
- if v && v != '' && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v
+ if v && v != '' && parser.regexp[:ABS_PATH] !~ v &&
+ parser.regexp[:REL_PATH] !~ v
raise InvalidComponentError,
"bad component(expected relative path component): #{v}"
end
@@ -835,9 +797,9 @@ module URI
end
private :check_path
- # protected setter for the path component +v+
+ # Protected setter for the path component +v+.
#
- # see also URI::Generic.path=
+ # See also URI::Generic.path=.
#
def set_path(v)
@path = v
@@ -852,10 +814,10 @@ module URI
#
# == Description
#
- # public setter for the path component +v+.
- # (with validation)
+ # Public setter for the path component +v+
+ # (with validation).
#
- # see also URI::Generic.check_path
+ # See also URI::Generic.check_path.
#
# == Usage
#
@@ -863,9 +825,7 @@ module URI
#
# uri = URI.parse("http://my.example.com/pub/files")
# uri.path = "/faq/"
- # # => "/faq/"
- # uri
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/faq/>
+ # uri.to_s #=> "http://my.example.com/faq/"
#
def path=(v)
check_path(v)
@@ -874,42 +834,6 @@ module URI
end
#
- # check the query +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :QUERY
- #
- # Can not have a opaque component defined,
- # with a query component defined.
- #
- def check_query(v)
- return v unless v
-
- # raise if both hier and opaque are not nil, because:
- # absoluteURI = scheme ":" ( hier_part | opaque_part )
- # hier_part = ( net_path | abs_path ) [ "?" query ]
- if @opaque
- raise InvalidURIError,
- "query conflicts with opaque"
- end
-
- if v && v != '' && parser.regexp[:QUERY] !~ v
- raise InvalidComponentError,
- "bad component(expected query component): #{v}"
- end
-
- return true
- end
- private :check_query
-
- # protected setter for the query component +v+
- #
- # see also URI::Generic.query=
- #
- def set_query(v)
- @query = v
- end
- protected :set_query
-
- #
# == Args
#
# +v+::
@@ -917,10 +841,7 @@ module URI
#
# == Description
#
- # public setter for the query component +v+.
- # (with validation)
- #
- # see also URI::Generic.check_query
+ # Public setter for the query component +v+.
#
# == Usage
#
@@ -928,21 +849,28 @@ module URI
#
# uri = URI.parse("http://my.example.com/?id=25")
# uri.query = "id=1"
- # # => "id=1"
- # uri
- # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/?id=1>
+ # uri.to_s #=> "http://my.example.com/?id=1"
#
def query=(v)
- check_query(v)
- set_query(v)
- v
+ return @query = nil unless v
+ raise InvalidURIError, "query conflicts with opaque" if @opaque
+
+ x = v.to_str
+ v = x.dup if x.equal? v
+ v.encode!(Encoding::UTF_8) rescue nil
+ v.delete!("\t\r\n")
+ v.force_encoding(Encoding::ASCII_8BIT)
+ raise InvalidURIError, "invalid percent escape: #{$1}" if /(%\H\H)/n.match(v)
+ v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n.freeze){'%%%02X' % $&.ord}
+ v.force_encoding(Encoding::US_ASCII)
+ @query = v
end
#
- # check the opaque +v+ component for RFC2396 compliance and
- # against the URI::Parser Regexp for :OPAQUE
+ # Checks the opaque +v+ component for RFC2396 compliance and
+ # against the +parser+ Regexp for :OPAQUE.
#
- # Can not have a host, port, user or path component defined,
+ # Can not have a host, port, user, or path component defined,
# with an opaque component defined.
#
def check_opaque(v)
@@ -953,7 +881,7 @@ module URI
# hier_part = ( net_path | abs_path ) [ "?" query ]
if @host || @port || @user || @path # userinfo = @user + ':' + @password
raise InvalidURIError,
- "can not set opaque with host, port, userinfo or path"
+ "cannot set opaque with host, port, userinfo or path"
elsif v && parser.regexp[:OPAQUE] !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
@@ -963,9 +891,9 @@ module URI
end
private :check_opaque
- # protected setter for the opaque component +v+
+ # Protected setter for the opaque component +v+.
#
- # see also URI::Generic.opaque=
+ # See also URI::Generic.opaque=.
#
def set_opaque(v)
@opaque = v
@@ -980,10 +908,10 @@ module URI
#
# == Description
#
- # public setter for the opaque component +v+.
- # (with validation)
+ # Public setter for the opaque component +v+
+ # (with validation).
#
- # see also URI::Generic.check_opaque
+ # See also URI::Generic.check_opaque.
#
def opaque=(v)
check_opaque(v)
@@ -992,29 +920,8 @@ module URI
end
#
- # check the fragment +v+ component against the URI::Parser Regexp for :FRAGMENT
- #
- def check_fragment(v)
- return v unless v
-
- if v && v != '' && parser.regexp[:FRAGMENT] !~ v
- raise InvalidComponentError,
- "bad component(expected fragment component): #{v}"
- end
-
- return true
- end
- private :check_fragment
-
- # protected setter for the fragment component +v+
- #
- # see also URI::Generic.fragment=
+ # Checks the fragment +v+ component against the +parser+ Regexp for :FRAGMENT.
#
- def set_fragment(v)
- @fragment = v
- end
- protected :set_fragment
-
#
# == Args
#
@@ -1023,10 +930,8 @@ module URI
#
# == Description
#
- # public setter for the fragment component +v+.
- # (with validation)
- #
- # see also URI::Generic.check_fragment
+ # Public setter for the fragment component +v+
+ # (with validation).
#
# == Usage
#
@@ -1034,18 +939,39 @@ module URI
#
# uri = URI.parse("http://my.example.com/?id=25#time=1305212049")
# uri.fragment = "time=1305212086"
- # # => "time=1305212086"
- # uri
- # #=> #<URI::HTTP:0x000000007a81f8 URL:http://my.example.com/?id=25#time=1305212086>
+ # uri.to_s #=> "http://my.example.com/?id=25#time=1305212086"
#
def fragment=(v)
- check_fragment(v)
- set_fragment(v)
- v
+ return @fragment = nil unless v
+
+ x = v.to_str
+ v = x.dup if x.equal? v
+ v.encode!(Encoding::UTF_8) rescue nil
+ v.delete!("\t\r\n")
+ v.force_encoding(Encoding::ASCII_8BIT)
+ v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X' % $&.ord}
+ v.force_encoding(Encoding::US_ASCII)
+ @fragment = v
end
#
- # Checks if URI has a path
+ # Returns true if URI is hierarchical.
+ #
+ # == Description
+ #
+ # URI has components listed in order of decreasing significance from left to right,
+ # see RFC3986 https://www.rfc-editor.org/rfc/rfc3986 1.2.3.
+ #
+ # == Usage
+ #
+ # require 'uri'
+ #
+ # uri = URI.parse("http://my.example.com/")
+ # uri.hierarchical?
+ # #=> true
+ # uri = URI.parse("mailto:joe@example.com")
+ # uri.hierarchical?
+ # #=> false
#
def hierarchical?
if @path
@@ -1056,7 +982,7 @@ module URI
end
#
- # Checks if URI is an absolute one
+ # Returns true if URI has a scheme (e.g. http:// or https://) specified.
#
def absolute?
if @scheme
@@ -1068,17 +994,17 @@ module URI
alias absolute absolute?
#
- # Checks if URI is relative
+ # Returns true if URI does not have a scheme (e.g. http:// or https://) specified.
#
def relative?
!absolute?
end
#
- # returns an Array of the path split on '/'
+ # Returns an Array of the path split on '/'.
#
def split_path(path)
- path.split(%r{/+}, -1)
+ path.split("/", -1)
end
private :split_path
@@ -1157,7 +1083,7 @@ module URI
#
# == Description
#
- # Destructive form of #merge
+ # Destructive form of #merge.
#
# == Usage
#
@@ -1165,8 +1091,7 @@ module URI
#
# uri = URI.parse("http://my.example.com")
# uri.merge!("/main.rbx?page=1")
- # p uri
- # # => #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
+ # uri.to_s # => "http://my.example.com/main.rbx?page=1"
#
def merge!(oth)
t = merge(oth)
@@ -1186,82 +1111,58 @@ module URI
#
# == Description
#
- # Merges two URI's.
+ # Merges two URIs.
#
# == Usage
#
# require 'uri'
#
# uri = URI.parse("http://my.example.com")
- # p uri.merge("/main.rbx?page=1")
- # # => #<URI::HTTP:0x2021f3b0 URL:http://my.example.com/main.rbx?page=1>
+ # uri.merge("/main.rbx?page=1")
+ # # => "http://my.example.com/main.rbx?page=1"
#
def merge(oth)
- begin
- base, rel = merge0(oth)
- rescue
- raise $!.class, $!.message
+ rel = parser.__send__(:convert_to_uri, oth)
+
+ if rel.absolute?
+ #raise BadURIError, "both URI are absolute" if absolute?
+ # hmm... should return oth for usability?
+ return rel
end
- if base == rel
- return base
+ unless self.absolute?
+ raise BadURIError, "both URI are relative"
end
- authority = rel.userinfo || rel.host || rel.port
+ base = self.dup
+
+ authority = rel.authority
# RFC2396, Section 5.2, 2)
if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
- base.set_fragment(rel.fragment) if rel.fragment
+ base.fragment=(rel.fragment) if rel.fragment
return base
end
- base.set_query(nil)
- base.set_fragment(nil)
+ base.query = nil
+ base.fragment=(nil)
# RFC2396, Section 5.2, 4)
- if !authority
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
- else
- # RFC2396, Section 5.2, 4)
- base.set_path(rel.path) if rel.path
+ if authority
+ base.set_authority(*authority)
+ base.set_path(rel.path)
+ elsif base.path && rel.path
+ base.set_path(merge_path(base.path, rel.path))
end
# RFC2396, Section 5.2, 7)
- base.set_userinfo(rel.userinfo) if rel.userinfo
- base.set_host(rel.host) if rel.host
- base.set_port(rel.port) if rel.port
- base.set_query(rel.query) if rel.query
- base.set_fragment(rel.fragment) if rel.fragment
+ base.query = rel.query if rel.query
+ base.fragment=(rel.fragment) if rel.fragment
return base
end # merge
alias + merge
- # return base and rel.
- # you can modify `base', but can not `rel'.
- def merge0(oth)
- oth = parser.send(:convert_to_uri, oth)
-
- if self.relative? && oth.relative?
- raise BadURIError,
- "both URI are relative"
- end
-
- if self.absolute? && oth.absolute?
- #raise BadURIError,
- # "both URI are absolute"
- # hmm... should return oth for usability?
- return oth, oth
- end
-
- if self.absolute?
- return self.dup, oth
- else
- return oth, oth
- end
- end
- private :merge0
-
# :stopdoc:
def route_from_path(src, dst)
case dst
@@ -1274,8 +1175,8 @@ module URI
return dst.dup
end
- src_path = src.scan(%r{(?:\A|[^/]+)/})
- dst_path = dst.scan(%r{(?:\A|[^/]+)/?})
+ src_path = src.scan(%r{[^/]*/})
+ dst_path = dst.scan(%r{[^/]*/?})
# discard same parts
while !dst_path.empty? && dst_path.first == src_path.first
@@ -1303,7 +1204,7 @@ module URI
# :stopdoc:
def route_from0(oth)
- oth = parser.send(:convert_to_uri, oth)
+ oth = parser.__send__(:convert_to_uri, oth)
if self.relative?
raise BadURIError,
"relative URI: #{self}"
@@ -1318,7 +1219,7 @@ module URI
end
rel = URI::Generic.new(nil, # it is relative URI
self.userinfo, self.host, self.port,
- self.registry, self.path, self.opaque,
+ nil, self.path, self.opaque,
self.query, self.fragment, parser)
if rel.userinfo != oth.userinfo ||
@@ -1338,15 +1239,15 @@ module URI
if rel.path && rel.path == oth.path
rel.set_path('')
- rel.set_query(nil) if rel.query == oth.query
+ rel.query = nil if rel.query == oth.query
return rel, rel
elsif rel.opaque && rel.opaque == oth.opaque
rel.set_opaque('')
- rel.set_query(nil) if rel.query == oth.query
+ rel.query = nil if rel.query == oth.query
return rel, rel
end
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
return oth, rel
end
private :route_from0
@@ -1360,18 +1261,18 @@ module URI
#
# == Description
#
- # Calculates relative path from oth to self
+ # Calculates relative path from oth to self.
#
# == Usage
#
# require 'uri'
#
# uri = URI.parse('http://my.example.com/main.rbx?page=1')
- # p uri.route_from('http://my.example.com')
- # #=> #<URI::Generic:0x20218858 URL:/main.rbx?page=1>
+ # uri.route_from('http://my.example.com')
+ # #=> #<URI::Generic /main.rbx?page=1>
#
def route_from(oth)
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
begin
oth, rel = route_from0(oth)
rescue
@@ -1400,22 +1301,32 @@ module URI
#
# == Description
#
- # Calculates relative path to oth from self
+ # Calculates relative path to oth from self.
#
# == Usage
#
# require 'uri'
#
# uri = URI.parse('http://my.example.com')
- # p uri.route_to('http://my.example.com/main.rbx?page=1')
- # #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1>
+ # uri.route_to('http://my.example.com/main.rbx?page=1')
+ # #=> #<URI::Generic /main.rbx?page=1>
#
def route_to(oth)
- parser.send(:convert_to_uri, oth).route_from(self)
+ parser.__send__(:convert_to_uri, oth).route_from(self)
end
#
- # Returns normalized URI
+ # Returns normalized URI.
+ #
+ # require 'uri'
+ #
+ # URI("HTTP://my.EXAMPLE.com").normalize
+ # #=> #<URI::HTTP http://my.example.com/>
+ #
+ # Normalization here means:
+ #
+ # * scheme and host are converted to lowercase,
+ # * an empty path component is set to "/".
#
def normalize
uri = dup
@@ -1424,10 +1335,10 @@ module URI
end
#
- # Destructive version of #normalize
+ # Destructive version of #normalize.
#
def normalize!
- if path && path == ''
+ if path&.empty?
set_path('/')
end
if scheme && scheme != scheme.downcase
@@ -1438,21 +1349,11 @@ module URI
end
end
- # returns the assemble String with path and query components
- def path_query
- str = @path
- if @query
- str += '?' + @query
- end
- str
- end
- private :path_query
-
#
- # Constructs String from URI
+ # Constructs String from URI.
#
def to_s
- str = ''
+ str = ''.dup
if @scheme
str << @scheme
str << ':'
@@ -1460,40 +1361,40 @@ module URI
if @opaque
str << @opaque
-
else
- if @registry
- str << @registry
- else
- if @host
- str << '//'
- end
- if self.userinfo
- str << self.userinfo
- str << '@'
- end
- if @host
- str << @host
- end
- if @port && @port != self.default_port
- str << ':'
- str << @port.to_s
- end
+ if @host || %w[file postgres].include?(@scheme)
+ str << '//'
+ end
+ if self.userinfo
+ str << self.userinfo
+ str << '@'
+ end
+ if @host
+ str << @host
+ end
+ if @port && @port != self.default_port
+ str << ':'
+ str << @port.to_s
+ end
+ if (@host || @port) && !@path.empty? && !@path.start_with?('/')
+ str << '/'
+ end
+ str << @path
+ if @query
+ str << '?'
+ str << @query
end
-
- str << path_query
end
-
if @fragment
str << '#'
str << @fragment
end
-
str
end
+ alias to_str to_s
#
- # Compares to URI's
+ # Compares two URIs.
#
def ==(oth)
if self.class == oth.class
@@ -1503,33 +1404,22 @@ module URI
end
end
+ # Returns the hash value.
def hash
self.component_ary.hash
end
+ # Compares with _oth_ for Hash.
def eql?(oth)
self.class == oth.class &&
parser == oth.parser &&
self.component_ary.eql?(oth.component_ary)
end
-=begin
-
---- URI::Generic#===(oth)
-
-=end
-# def ===(oth)
-# raise NotImplementedError
-# end
-
-=begin
-=end
-
-
- # returns an Array of the components defined from the COMPONENT Array
+ # Returns an Array of the components defined from the COMPONENT Array.
def component_ary
component.collect do |x|
- self.send(x)
+ self.__send__(x)
end
end
protected :component_ary
@@ -1537,24 +1427,24 @@ module URI
# == Args
#
# +components+::
- # Multiple Symbol arguments defined in URI::HTTP
+ # Multiple Symbol arguments defined in URI::HTTP.
#
# == Description
#
- # Selects specified components from URI
+ # Selects specified components from URI.
#
# == Usage
#
# require 'uri'
#
# uri = URI.parse('http://myuser:mypass@my.example.com/test.rbx')
- # p uri.select(:userinfo, :host, :path)
+ # uri.select(:userinfo, :host, :path)
# # => ["myuser:mypass", "my.example.com", "/test.rbx"]
#
def select(*components)
components.collect do |c|
if component.include?(c)
- self.send(c)
+ self.__send__(c)
else
raise ArgumentError,
"expected of components of #{self.class} (#{self.class.component.join(', ')})"
@@ -1562,9 +1452,8 @@ module URI
end
end
- @@to_s = Kernel.instance_method(:to_s)
- def inspect
- @@to_s.bind(self).call.sub!(/>\z/) {" URL:#{self}>"}
+ def inspect # :nodoc:
+ "#<#{self.class} #{self}>"
end
#
@@ -1575,8 +1464,8 @@ module URI
#
# == Description
#
- # attempt to parse other URI +oth+
- # return [parsed_oth, self]
+ # Attempts to parse other URI +oth+,
+ # returns [parsed_oth, self].
#
# == Usage
#
@@ -1584,7 +1473,7 @@ module URI
#
# uri = URI.parse("http://my.example.com")
# uri.coerce("http://foo.com")
- # #=> [#<URI::HTTP:0x00000000bcb028 URL:http://foo.com/>, #<URI::HTTP:0x00000000d92178 URL:http://my.example.com>]
+ # #=> [#<URI::HTTP http://foo.com>, #<URI::HTTP http://my.example.com>]
#
def coerce(oth)
case oth
@@ -1597,54 +1486,66 @@ module URI
return oth, self
end
- # returns a proxy URI.
+ # Returns a proxy URI.
# The proxy URI is obtained from environment variables such as http_proxy,
# ftp_proxy, no_proxy, etc.
# If there is no proper proxy, nil is returned.
#
+ # If the optional parameter +env+ is specified, it is used instead of ENV.
+ #
# Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
- # are examined too.
+ # are examined, too.
#
# But http_proxy and HTTP_PROXY is treated specially under CGI environment.
# It's because HTTP_PROXY may be set by Proxy: header.
# So HTTP_PROXY is not used.
# http_proxy is not used too if the variable is case insensitive.
# CGI_HTTP_PROXY can be used instead.
- def find_proxy
+ def find_proxy(env=ENV)
raise BadURIError, "relative URI: #{self}" if self.relative?
name = self.scheme.downcase + '_proxy'
proxy_uri = nil
- if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
+ if name == 'http_proxy' && env.include?('REQUEST_METHOD') # CGI?
# HTTP_PROXY conflicts with *_proxy for proxy settings and
# HTTP_* for header information in CGI.
# So it should be careful to use it.
- pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
+ pairs = env.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
case pairs.length
when 0 # no proxy setting anyway.
proxy_uri = nil
when 1
k, _ = pairs.shift
- if k == 'http_proxy' && ENV[k.upcase] == nil
+ if k == 'http_proxy' && env[k.upcase] == nil
# http_proxy is safe to use because ENV is case sensitive.
- proxy_uri = ENV[name]
+ proxy_uri = env[name]
else
proxy_uri = nil
end
else # http_proxy is safe to use because ENV is case sensitive.
- proxy_uri = ENV.to_hash[name]
+ proxy_uri = env.to_hash[name]
end
if !proxy_uri
# Use CGI_HTTP_PROXY. cf. libwww-perl.
- proxy_uri = ENV["CGI_#{name.upcase}"]
+ proxy_uri = env["CGI_#{name.upcase}"]
end
elsif name == 'http_proxy'
- unless proxy_uri = ENV[name]
- if proxy_uri = ENV[name.upcase]
- warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.'
+ if RUBY_ENGINE == 'jruby' && p_addr = ENV_JAVA['http.proxyHost']
+ p_port = ENV_JAVA['http.proxyPort']
+ if p_user = ENV_JAVA['http.proxyUser']
+ p_pass = ENV_JAVA['http.proxyPass']
+ proxy_uri = "http://#{p_user}:#{p_pass}@#{p_addr}:#{p_port}"
+ else
+ proxy_uri = "http://#{p_addr}:#{p_port}"
+ end
+ else
+ unless proxy_uri = env[name]
+ if proxy_uri = env[name.upcase]
+ warn 'The environment variable HTTP_PROXY is discouraged. Please use http_proxy instead.', uplevel: 1
+ end
end
end
else
- proxy_uri = ENV[name] || ENV[name.upcase]
+ proxy_uri = env[name] || env[name.upcase]
end
if proxy_uri.nil? || proxy_uri.empty?
@@ -1652,7 +1553,6 @@ module URI
end
if self.hostname
- require 'socket'
begin
addr = IPSocket.getaddress(self.hostname)
return nil if /\A127\.|\A::1\z/ =~ addr
@@ -1661,15 +1561,32 @@ module URI
end
name = 'no_proxy'
- if no_proxy = ENV[name] || ENV[name.upcase]
- no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
- if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
- (!port || self.port == port.to_i)
- return nil
- end
- }
+ if no_proxy = env[name] || env[name.upcase]
+ return nil unless URI::Generic.use_proxy?(self.hostname, addr, self.port, no_proxy)
end
URI.parse(proxy_uri)
end
+
+ def self.use_proxy?(hostname, addr, port, no_proxy) # :nodoc:
+ hostname = hostname.downcase
+ dothostname = ".#{hostname}"
+ no_proxy.scan(/([^:,\s]+)(?::(\d+))?/) {|p_host, p_port|
+ if !p_port || port == p_port.to_i
+ if p_host.start_with?('.')
+ return false if hostname.end_with?(p_host.downcase)
+ else
+ return false if dothostname.end_with?(".#{p_host.downcase}")
+ end
+ if addr
+ begin
+ return false if IPAddr.new(p_host).include?(addr)
+ rescue IPAddr::InvalidAddressError
+ next
+ end
+ end
+ end
+ }
+ true
+ end
end
end