Class: URI::Generic

Inherits:
Object
  • Object
show all
Includes:
URI
Defined in:
lib/uri/generic.rb

Overview

Base class for all URI classes. Implements generic URI syntax as per RFC 2396.

Direct Known Subclasses

FTP, HTTP, LDAP, MailTo

Constant Summary collapse

DEFAULT_PORT =

A Default port of nil for URI::Generic

nil
COMPONENT =

An Array of the available components for URI::Generic

[
  :scheme,
  :userinfo, :host, :port, :registry,
  :path, :opaque,
  :query,
  :fragment
].freeze
USE_REGISTRY =

Default to not use the registry for a URI::Generic

false
@@to_s =
Kernel.instance_method(:to_s)

Constants included from URI

DEFAULT_PARSER, HTML5ASCIIINCOMPAT, TBLDECWWWCOMP_, TBLENCWWWCOMP_, VERSION, VERSION_CODE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from URI

decode_www_form, decode_www_form_component, encode_www_form, encode_www_form_component, extract, join, parse, regexp, scheme_list, split

Methods included from Escape

#escape, #unescape

Constructor Details

#initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = DEFAULT_PARSER, arg_check = false) ⇒ Generic

Args

scheme

Protocol scheme, i.e. ‘http’,‘ftp’,‘mailto’ and so on.

userinfo

User name and password, i.e. ‘sdmitry:bla’

host

Server host name

port

Server port

registry

Registry of naming authorities.

path

Path on server

opaque

Opaque part

query

Query data

fragment

A part of URI after ‘#’ sign

parser

Parser for internal use [URI::DEFAULT_PARSER by default]

arg_check

Check arguments [false by default]

Description

Creates a new URI::Generic instance from “generic” components without check.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/uri/generic.rb', line 173

def initialize(scheme,
               userinfo, host, port, registry,
               path, opaque,
               query,
               fragment,
               parser = DEFAULT_PARSER,
               arg_check = false)
  @scheme = nil
  @user = nil
  @password = nil
  @host = nil
  @port = nil
  @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.port = port
    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_path(path)
    self.set_query(query)
    self.set_opaque(opaque)
    self.set_registry(registry)
    self.set_fragment(fragment)
  end
  if @registry && !self.class.use_registry
    raise InvalidURIError,
      "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
  end

  @scheme.freeze if @scheme
  self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
  self.set_port(self.default_port) if self.default_port && !@port
end

Instance Attribute Details

#fragmentObject

returns the fragment component of the URI.

URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies"


292
293
294
# File 'lib/uri/generic.rb', line 292

def fragment
  @fragment
end

#hostObject

returns the host component of the URI.

URI("http://foo/bar/baz").host #=> "foo"

It returns nil if no host component.

URI("mailto:[email protected]").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"


250
251
252
# File 'lib/uri/generic.rb', line 250

def host
  @host
end

#opaqueObject

returns the opaque part of the URI.

URI("mailto:[email protected]").opaque #=> "[email protected]"

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)


286
287
288
# File 'lib/uri/generic.rb', line 286

def opaque
  @opaque
end

#pathObject

returns the path component of the URI.

URI("http://foo/bar/baz").path #=> "/bar/baz"


270
271
272
# File 'lib/uri/generic.rb', line 270

def path
  @path
end

#portObject

returns the port component of the URI.

URI("http://foo/bar/baz").port #=> "80"

URI("http://foo:8080/bar/baz").port #=> "8080"


258
259
260
# File 'lib/uri/generic.rb', line 258

def port
  @port
end

#queryObject

returns the query component of the URI.

URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar"


276
277
278
# File 'lib/uri/generic.rb', line 276

def query
  @query
end

#registryObject

returns the registry component of the URI.

(see RFC2396 Section 3.2)


264
265
266
# File 'lib/uri/generic.rb', line 264

def registry
  @registry
end

#schemeObject

returns the scheme component of the URI.

URI("http://foo/bar/baz").scheme #=> "http"


228
229
230
# File 'lib/uri/generic.rb', line 228

def scheme
  @scheme
end

Class Method Details

.build(args) ⇒ Object

Synopsis

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.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/uri/generic.rb', line 121

def self.build(args)
  if args.kind_of?(Array) &&
      args.size == ::URI::Generic::COMPONENT.size
    tmp = args.dup
  elsif args.kind_of?(Hash)
    tmp = ::URI::Generic::COMPONENT.collect do |c|
      if args.include?(c)
        args[c]
      else
        nil
      end
    end
  else
    component = self.class.component rescue ::URI::Generic::COMPONENT
    raise ArgumentError,
    "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
  end

  tmp << nil
  tmp << true
  return self.new(*tmp)
end

.build2(args) ⇒ Object

Synopsis

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.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/uri/generic.rb', line 83

def self.build2(args)
  begin
    return self.build(args)
  rescue InvalidComponentError
    if args.kind_of?(Array)
      return self.build(args.collect{|x|
        if x.is_a?(String)
          DEFAULT_PARSER.escape(x)
        else
          x
        end
      })
    elsif args.kind_of?(Hash)
      tmp = {}
      args.each do |key, value|
        tmp[key] = if value
            DEFAULT_PARSER.escape(value)
          else
            value
          end
      end
      return self.build(tmp)
    end
  end
end

.componentObject

Components of the URI in the order.



54
55
56
# File 'lib/uri/generic.rb', line 54

def self.component
  self::COMPONENT
end

.default_portObject

Returns default port



29
30
31
# File 'lib/uri/generic.rb', line 29

def self.default_port
  self::DEFAULT_PORT
end

.use_registryObject

Returns whether a registry of naming authorities are being used.



67
68
69
# File 'lib/uri/generic.rb', line 67

def self.use_registry
  self::USE_REGISTRY
end

Instance Method Details

#==(oth) ⇒ Object

Compares to URI’s



1498
1499
1500
1501
1502
1503
1504
# File 'lib/uri/generic.rb', line 1498

def ==(oth)
  if self.class == oth.class
    self.normalize.component_ary == oth.normalize.component_ary
  else
    false
  end
end

#absolute?Boolean Also known as: absolute

Checks if URI is an absolute one

Returns:

  • (Boolean)


1061
1062
1063
1064
1065
1066
1067
# File 'lib/uri/generic.rb', line 1061

def absolute?
  if @scheme
    true
  else
    false
  end
end

#coerce(oth) ⇒ Object

Args

v

URI or String

Description

attempt to parse other URI +oth+
return [parsed_oth, self]

Usage

require '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>]


1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
# File 'lib/uri/generic.rb', line 1589

def coerce(oth)
  case oth
  when String
    oth = parser.parse(oth)
  else
    super
  end

  return oth, self
end

#componentObject

Components of the URI in the order.



321
322
323
# File 'lib/uri/generic.rb', line 321

def component
  self.class.component
end

#default_portObject

Returns default port



36
37
38
# File 'lib/uri/generic.rb', line 36

def default_port
  self.class.default_port
end

#eql?(oth) ⇒ Boolean

Returns:

  • (Boolean)


1510
1511
1512
1513
1514
# File 'lib/uri/generic.rb', line 1510

def eql?(oth)
  self.class == oth.class &&
  parser == oth.parser &&
  self.component_ary.eql?(oth.component_ary)
end

#find_proxyObject

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.

Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.) 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.

Raises:



1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
# File 'lib/uri/generic.rb', line 1613

def find_proxy
  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?
    # 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 }
    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
        # http_proxy is safe to use because ENV is case sensitive.
        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]
    end
    if !proxy_uri
      # Use CGI_HTTP_PROXY.  cf. libwww-perl.
      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.'
      end
    end
  else
    proxy_uri = ENV[name] || ENV[name.upcase]
  end

  if proxy_uri.nil? || proxy_uri.empty?
    return nil
  end

  if self.hostname
    require 'socket'
    begin
      addr = IPSocket.getaddress(self.hostname)
      return nil if /\A127\.|\A::1\z/ =~ addr
    rescue SocketError
    end
  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
    }
  end
  URI.parse(proxy_uri)
end

#hashObject



1506
1507
1508
# File 'lib/uri/generic.rb', line 1506

def hash
  self.component_ary.hash
end

#hierarchical?Boolean

Checks if URI has a path

Returns:

  • (Boolean)


1050
1051
1052
1053
1054
1055
1056
# File 'lib/uri/generic.rb', line 1050

def hierarchical?
  if @path
    true
  else
    false
  end
end

#hostnameObject

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]”



660
661
662
663
# File 'lib/uri/generic.rb', line 660

def hostname
  v = self.host
  /\A\[(.*)\]\z/ =~ v ? $1 : v
end

#hostname=(v) ⇒ Object

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(“foo/bar”) p u.to_s #=> “foo/bar” u.hostname = “::1” p u.to_s #=> “[::1]/bar

If the argument seems IPv6 address, it is wrapped by brackets.



678
679
680
681
# File 'lib/uri/generic.rb', line 678

def hostname=(v)
  v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v
  self.host = v
end

#inspectObject



1566
1567
1568
# File 'lib/uri/generic.rb', line 1566

def inspect
  @@to_s.bind(self).call.sub!(/>\z/) {" URL:#{self}>"}
end

#merge(oth) ⇒ Object Also known as: +

Args

oth

URI or String

Description

Merges two URI’s.

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>


1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
# File 'lib/uri/generic.rb', line 1199

def merge(oth)
  begin
    base, rel = merge0(oth)
  rescue
    raise $!.class, $!.message
  end

  if base == rel
    return base
  end

  authority = rel.userinfo || rel.host || rel.port

  # RFC2396, Section 5.2, 2)
  if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
    base.set_fragment(rel.fragment) if rel.fragment
    return base
  end

  base.set_query(nil)
  base.set_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
  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

  return base
end

#merge!(oth) ⇒ Object

Args

oth

URI or String

Description

Destructive form of #merge

Usage

require '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>


1171
1172
1173
1174
1175
1176
1177
1178
1179
# File 'lib/uri/generic.rb', line 1171

def merge!(oth)
  t = merge(oth)
  if self == t
    nil
  else
    replace!(t)
    self
  end
end

#normalizeObject

Returns normalized URI



1420
1421
1422
1423
1424
# File 'lib/uri/generic.rb', line 1420

def normalize
  uri = dup
  uri.normalize!
  uri
end

#normalize!Object

Destructive version of #normalize



1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
# File 'lib/uri/generic.rb', line 1429

def normalize!
  if path && path == ''
    set_path('/')
  end
  if scheme && scheme != scheme.downcase
    set_scheme(self.scheme.downcase)
  end
  if host && host != host.downcase
    set_host(self.host.downcase)
  end
end

#parserObject

returns the parser to be used.

Unless a URI::Parser is defined, then DEFAULT_PARSER is used.



298
299
300
301
302
303
304
# File 'lib/uri/generic.rb', line 298

def parser
  if !defined?(@parser) || !@parser
    DEFAULT_PARSER
  else
    @parser || DEFAULT_PARSER
  end
end

#passwordObject

returns the password component



587
588
589
# File 'lib/uri/generic.rb', line 587

def password
  @password
end

#password=(password) ⇒ Object

Args

v

String

Description

public setter for the password component. (with validation)

see also URI::Generic.check_password

Usage

require 'uri'

uri = URI.parse("http://john:[email protected]")
uri.password = "V3ry_S3nsit1ve"
# =>  "V3ry_S3nsit1ve"
uri
#=> #<URI::HTTP:0x00000000881d90 URL:http://john:[email protected]>


512
513
514
515
516
# File 'lib/uri/generic.rb', line 512

def password=(password)
  check_password(password)
  set_password(password)
  # returns password
end

#relative?Boolean

Checks if URI is relative

Returns:

  • (Boolean)


1073
1074
1075
# File 'lib/uri/generic.rb', line 1073

def relative?
  !absolute?
end

#route_from(oth) ⇒ Object Also known as: -

Args

oth

URI or String

Description

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>


1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
# File 'lib/uri/generic.rb', line 1373

def route_from(oth)
  # you can modify `rel', but can not `oth'.
  begin
    oth, rel = route_from0(oth)
  rescue
    raise $!.class, $!.message
  end
  if oth == rel
    return rel
  end

  rel.set_path(route_from_path(oth.path, self.path))
  if rel.path == './' && self.query
    # "./?foo" -> "?foo"
    rel.set_path('')
  end

  return rel
end

#route_to(oth) ⇒ Object

Args

oth

URI or String

Description

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>


1413
1414
1415
# File 'lib/uri/generic.rb', line 1413

def route_to(oth)
  parser.send(:convert_to_uri, oth).route_from(self)
end

#select(*components) ⇒ Object

Args

components

Multiple Symbol arguments defined in URI::HTTP

Description

Selects specified components from URI

Usage

require 'uri'

uri = URI.parse('http://myuser:[email protected]/test.rbx')
p uri.select(:userinfo, :host, :path)
# => ["myuser:mypass", "my.example.com", "/test.rbx"]


1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
# File 'lib/uri/generic.rb', line 1554

def select(*components)
  components.collect do |c|
    if component.include?(c)
      self.send(c)
    else
      raise ArgumentError,
        "expected of components of #{self.class} (#{self.class.component.join(', ')})"
    end
  end
end

#to_sObject

Constructs String from URI



1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
# File 'lib/uri/generic.rb', line 1454

def to_s
  str = ''
  if @scheme
    str << @scheme
    str << ':'
  end

  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
    end

    str << path_query
  end

  if @fragment
    str << '#'
    str << @fragment
  end

  str
end

#userObject

returns the user component



582
583
584
# File 'lib/uri/generic.rb', line 582

def user
  @user
end

#user=(user) ⇒ Object

Args

v

String

Description

public setter for the user component. (with validation)

see also URI::Generic.check_user

Usage

require 'uri'

uri = URI.parse("http://john:[email protected]")
uri.user = "sam"
# =>  "sam"
uri
#=> #<URI::HTTP:0x00000000881d90 URL:http://sam:[email protected]>


483
484
485
486
487
# File 'lib/uri/generic.rb', line 483

def user=(user)
  check_user(user)
  set_user(user)
  # returns user
end

#userinfoObject

returns the userinfo, either as ‘user’ or ‘user:password’



571
572
573
574
575
576
577
578
579
# File 'lib/uri/generic.rb', line 571

def userinfo
  if @user.nil?
    nil
  elsif @password.nil?
    @user
  else
    @user + ':' + @password
  end
end

#userinfo=(userinfo) ⇒ Object

Sets userinfo, argument is string like ‘name:pass’



451
452
453
454
455
456
457
458
# File 'lib/uri/generic.rb', line 451

def userinfo=(userinfo)
  if userinfo.nil?
    return nil
  end
  check_userinfo(*userinfo)
  set_userinfo(*userinfo)
  # returns userinfo
end