Class: Addressable::URI

Inherits:
Object
  • Object
show all
Defined in:
lib/addressable/uri.rb

Overview

This is an implementation of a URI parser based on <a href="RFC">www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>, <a href="RFC">www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>.

Defined Under Namespace

Modules: CharacterClasses Classes: InvalidURIError

Constant Summary

SLASH =
'/'
EMPTYSTR =
''
URIREGEX =
/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/
PORT_MAPPING =
{
  "http" => 80,
  "https" => 443,
  "ftp" => 21,
  "tftp" => 69,
  "sftp" => 22,
  "ssh" => 22,
  "svn+ssh" => 22,
  "telnet" => 23,
  "nntp" => 119,
  "gopher" => 70,
  "wais" => 210,
  "ldap" => 389,
  "prospero" => 1525
}
NORMPATH =
/^(?!\/)[^\/:]*:.*$/
PARENT1 =

Resolves paths to their simplest form.

Returns:

  • (String)

    The normalized path.

'.'
PARENT2 =
'..'
NPATH1 =
/\/\.\/|\/\.$/
NPATH2 =
/\/([^\/]+)\/\.\.\/|\/([^\/]+)\/\.\.$/
NPATH3 =
/^\.\.?\/?/
NPATH4 =
/^\/\.\.?\/|^(\/\.\.?)+\/?$/

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Addressable::URI) initialize(options = {})

Creates a new uri object from component parts.

Parameters:

  • [String, (Hash)

    a customizable set of options



695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# File 'lib/addressable/uri.rb', line 695

def initialize(options={})
  if options.has_key?(:authority)
    if (options.keys & [:userinfo, :user, :password, :host, :port]).any?
      raise ArgumentError,
        "Cannot specify both an authority and any of the components " +
        "within the authority."
    end
  end
  if options.has_key?(:userinfo)
    if (options.keys & [:user, :password]).any?
      raise ArgumentError,
        "Cannot specify both a userinfo and either the user or password."
    end
  end

  self.defer_validation do
    # Bunch of crazy logic required because of the composite components
    # like userinfo and authority.
    self.scheme = options[:scheme] if options[:scheme]
    self.user = options[:user] if options[:user]
    self.password = options[:password] if options[:password]
    self.userinfo = options[:userinfo] if options[:userinfo]
    self.host = options[:host] if options[:host]
    self.port = options[:port] if options[:port]
    self.authority = options[:authority] if options[:authority]
    self.path = options[:path] if options[:path]
    self.query = options[:query] if options[:query]
    self.query_values = options[:query_values] if options[:query_values]
    self.fragment = options[:fragment] if options[:fragment]
  end
end

Class Method Details

+ (Addressable::URI) convert_path(path)

Converts a path to a file scheme URI. If the path supplied is relative, it will be returned as a relative URI. If the path supplied is actually a non-file URI, it will parse the URI as if it had been parsed with Addressable::URI.parse. Handles all of the various Microsoft-specific formats for specifying paths.

Examples:

base = Addressable::URI.convert_path("/absolute/path/")
uri = Addressable::URI.convert_path("relative/path")
(base + uri).to_s
#=> "file:///absolute/path/relative/path"

Addressable::URI.convert_path(
  "c:\\windows\\My Documents 100%20\\foo.txt"
).to_s
#=> "file:///c:/windows/My%20Documents%20100%20/foo.txt"

Addressable::URI.convert_path("http://example.com/").to_s
#=> "http://example.com/"

Parameters:

  • path (String, Addressable::URI, #to_str)

    Typically a String path to a file or directory, but will return a sensible return value if an absolute URI is supplied instead.

Returns:

  • (Addressable::URI)

    The parsed file scheme URI or the original URI if some other URI scheme was provided.



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/addressable/uri.rb', line 229

def self.convert_path(path)
  # If we were given nil, return nil.
  return nil unless path
  # If a URI object is passed, just return itself.
  return path if path.kind_of?(self)
  if !path.respond_to?(:to_str)
    raise TypeError, "Can't convert #{path.class} into String."
  end
  # Otherwise, convert to a String
  path = path.to_str.strip

  path.gsub!(/^file:\/?\/?/, EMPTYSTR) if path =~ /^file:\/?\/?/
  path = SLASH + path if path =~ /^([a-zA-Z])[\|:]/
  uri = self.parse(path)

  if uri.scheme == nil
    # Adjust windows-style uris
    uri.path.gsub!(/^\/?([a-zA-Z])[\|:][\\\/]/) do
      "/#{$1.downcase}:/"
    end
    uri.path.gsub!(/\\/, SLASH)
    if File.exists?(uri.path) &&
        File.stat(uri.path).directory?
      uri.path.gsub!(/\/$/, EMPTYSTR)
      uri.path = uri.path + '/'
    end

    # If the path is absolute, set the scheme and host.
    if uri.path =~ /^\//
      uri.scheme = "file"
      uri.host = EMPTYSTR
    end
    uri.normalize!
  end

  return uri
end

+ (String, Addressable::URI) encode(uri, returning = String) Also known as: escape

Percent encodes any special characters in the URI.

Parameters:

  • uri (String, Addressable::URI, #to_str)

    The URI to encode.

  • returning (Class) (defaults to: String)

    The type of object to return. This value may only be set to String or Addressable::URI. All other values are invalid. Defaults to String.

Returns:

  • (String, Addressable::URI)

    The encoded URI. The return type is determined by the returning parameter.



490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
# File 'lib/addressable/uri.rb', line 490

def self.encode(uri, returning=String)
  return nil if uri.nil?

  begin
    uri = uri.to_str
  rescue NoMethodError, TypeError
    raise TypeError, "Can't convert #{uri.class} into String."
  end if !uri.is_a? String

  if ![String, ::Addressable::URI].include?(returning)
    raise TypeError,
      "Expected Class (String or Addressable::URI), " +
      "got #{returning.inspect}"
  end
  uri_object = uri.kind_of?(self) ? uri : self.parse(uri)
  encoded_uri = Addressable::URI.new(
    :scheme => self.encode_component(uri_object.scheme,
      Addressable::URI::CharacterClasses::SCHEME),
    :authority => self.encode_component(uri_object.authority,
      Addressable::URI::CharacterClasses::AUTHORITY),
    :path => self.encode_component(uri_object.path,
      Addressable::URI::CharacterClasses::PATH),
    :query => self.encode_component(uri_object.query,
      Addressable::URI::CharacterClasses::QUERY),
    :fragment => self.encode_component(uri_object.fragment,
      Addressable::URI::CharacterClasses::FRAGMENT)
  )
  if returning == String
    return encoded_uri.to_s
  elsif returning == ::Addressable::URI
    return encoded_uri
  end
end

+ (String) form_encode(form_values, sort = false)

Encodes a set of key/value pairs according to the rules for the application/x-www-form-urlencoded MIME type.

Parameters:

  • form_values (#to_hash, #to_ary)

    The form values to encode.

  • sort (TrueClass, FalseClass) (defaults to: false)

    Sort the key/value pairs prior to encoding. Defaults to false.

Returns:

  • (String)

    The encoded value.



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
# File 'lib/addressable/uri.rb', line 614

def self.form_encode(form_values, sort=false)
  if form_values.respond_to?(:to_hash)
    form_values = form_values.to_hash.to_a
  elsif form_values.respond_to?(:to_ary)
    form_values = form_values.to_ary
  else
    raise TypeError, "Can't convert #{form_values.class} into Array."
  end
  form_values = form_values.map do |(key, value)|
    [key.to_s, value.to_s]
  end
  if sort
    # Useful for OAuth and optimizing caching systems
    form_values = form_values.sort
  end
  escaped_form_values = form_values.map do |(key, value)|
    # Line breaks are CRLF pairs
    [
      self.encode_component(
        key.gsub(/(\r\n|\n|\r)/, "\r\n"),
        CharacterClasses::UNRESERVED
      ).gsub("%20", "+"),
      self.encode_component(
        value.gsub(/(\r\n|\n|\r)/, "\r\n"),
        CharacterClasses::UNRESERVED
      ).gsub("%20", "+")
    ]
  end
  return (escaped_form_values.map do |(key, value)|
    "#{key}=#{value}"
  end).join("&")
end

+ (Array) form_unencode(encoded_value)

Decodes a String according to the rules for the application/x-www-form-urlencoded MIME type.

Parameters:

  • encoded_value (String, #to_str)

    The form values to decode.

Returns:

  • (Array)

    The decoded values. This is not a Hash because of the possibility for duplicate keys.



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
# File 'lib/addressable/uri.rb', line 658

def self.form_unencode(encoded_value)
  if !encoded_value.respond_to?(:to_str)
    raise TypeError, "Can't convert #{encoded_value.class} into String."
  end
  encoded_value = encoded_value.to_str
  split_values = encoded_value.split("&").map do |pair|
    pair.split("=", 2)
  end
  return split_values.map do |(key, value)|
    [
      key ? self.unencode_component(
        key.gsub("+", "%20")).gsub(/(\r\n|\n|\r)/, "\n") : nil,
      value ? (self.unencode_component(
        value.gsub("+", "%20")).gsub(/(\r\n|\n|\r)/, "\n")) : nil
    ]
  end
end

+ (Addressable::URI) heuristic_parse(uri, hints = {})

Converts an input to a URI. The input does not have to be a valid URI — the method will use heuristics to guess what URI was intended. This is not standards-compliant, merely user-friendly.

Parameters:

  • uri (String, Addressable::URI, #to_str)

    The URI string to parse. No parsing is performed if the object is already an Addressable::URI.

  • hints (Hash) (defaults to: {})

    A Hash of hints to the heuristic parser. Defaults to {:scheme => "http"}.

Returns:



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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
# File 'lib/addressable/uri.rb', line 156

def self.heuristic_parse(uri, hints={})
  # If we were given nil, return nil.
  return nil unless uri
  # If a URI object is passed, just return itself.
  return uri.dup if uri.kind_of?(self)
  if !uri.respond_to?(:to_str)
    raise TypeError, "Can't convert #{uri.class} into String."
  end
  # Otherwise, convert to a String
  uri = uri.to_str.dup
  hints = {
    :scheme => "http"
  }.merge(hints)
  case uri
  when /^http:\/+/
    uri.gsub!(/^http:\/+/, "http://")
  when /^https:\/+/
    uri.gsub!(/^https:\/+/, "https://")
  when /^feed:\/+http:\/+/
    uri.gsub!(/^feed:\/+http:\/+/, "feed:http://")
  when /^feed:\/+/
    uri.gsub!(/^feed:\/+/, "feed://")
  when /^file:\/+/
    uri.gsub!(/^file:\/+/, "file:///")
  end
  parsed = self.parse(uri)
  if parsed.scheme =~ /^[^\/?#\.]+\.[^\/?#]+$/
    parsed = self.parse(hints[:scheme] + "://" + uri)
  end
  if parsed.path.include?(".")
    new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1]
    if new_host
      parsed.defer_validation do
        new_path = parsed.path.gsub(
          Regexp.new("^" + Regexp.escape(new_host)), EMPTYSTR)
        parsed.host = new_host
        parsed.path = new_path
        parsed.scheme = hints[:scheme] unless parsed.scheme
      end
    end
  end
  return parsed
end

+ (Object) ip_based_schemes

Returns an array of known ip-based schemes. These schemes typically use a similar URI form: //<user>:<password>@<host>:<port>/<url-path>



1128
1129
1130
# File 'lib/addressable/uri.rb', line 1128

def self.ip_based_schemes
  return self.port_mapping.keys
end

+ (Addressable::URI) join(*uris)

Joins several URIs together.

Examples:

base = "http://example.com/"
uri = Addressable::URI.parse("relative/path")
Addressable::URI.join(base, uri)
#=> #<Addressable::URI:0xcab390 URI:http://example.com/relative/path>

Parameters:

Returns:



280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/addressable/uri.rb', line 280

def self.join(*uris)
  uri_objects = uris.collect do |uri|
    if !uri.respond_to?(:to_str)
      raise TypeError, "Can't convert #{uri.class} into String."
    end
    uri.kind_of?(self) ? uri : self.parse(uri.to_str)
  end
  result = uri_objects.shift.dup
  for uri in uri_objects
    result.join!(uri)
  end
  return result
end

+ (String) normalize_component(component, character_class = CharacterClasses::RESERVED + CharacterClasses::UNRESERVED)

Normalizes the encoding of a URI component.

Examples:

Addressable::URI.normalize_component("simpl%65/%65xampl%65", "b-zB-Z")
=> "simple%2Fex%61mple"
Addressable::URI.normalize_component(
  "simpl%65/%65xampl%65", /[^b-zB-Z]/
)
=> "simple%2Fex%61mple"
Addressable::URI.normalize_component(
  "simpl%65/%65xampl%65",
  Addressable::URI::CharacterClasses::UNRESERVED
)
=> "simple%2Fexample"

Parameters:

  • component (String, #to_str)

    The URI component to encode.

  • character_class (String, Regexp) (defaults to: CharacterClasses::RESERVED + CharacterClasses::UNRESERVED)

    The characters which are not percent encoded. If a String is passed, the String must be formatted as a regular expression character class. (Do not include the surrounding square brackets.) For example, "b-zB-Z0-9" would cause everything but the letters 'b' through 'z' and the numbers '0' through '9' to be percent encoded. If a Regexp is passed, the value /[^b-zB-Z0-9]/ would have the same effect. A set of useful String values may be found in the Addressable::URI::CharacterClasses module. The default value is the reserved plus unreserved character classes specified in <a href=“RFC”>www.ietf.org/rfc/rfc3986.txt“>RFC 3986</a>.

Returns:

  • (String)

    The normalized component.



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# File 'lib/addressable/uri.rb', line 440

def self.normalize_component(component, character_class=
    CharacterClasses::RESERVED + CharacterClasses::UNRESERVED)
  return nil if component.nil?

  begin
    component = component.to_str
  rescue NoMethodError, TypeError
    raise TypeError, "Can't convert #{component.class} into String."
  end if !component.is_a? String

  if ![String, Regexp].include?(character_class.class)
    raise TypeError,
      "Expected String or Regexp, got #{character_class.inspect}"
  end
  if character_class.kind_of?(String)
    character_class = /[^#{character_class}]/
  end
  if component.respond_to?(:force_encoding)
    # We can't perform regexps on invalid UTF sequences, but
    # here we need to, so switch to ASCII.
    component = component.dup
    component.force_encoding(Encoding::ASCII_8BIT)
  end
  unencoded = self.unencode_component(component)
  begin
    encoded = self.encode_component(
      Addressable::IDNA.unicode_normalize_kc(unencoded),
      character_class
    )
  rescue ArgumentError
    encoded = self.encode_component(unencoded)
  end
  return encoded
end

+ (String, Addressable::URI) normalized_encode(uri, returning = String)

Normalizes the encoding of a URI. Characters within a hostname are not percent encoded to allow for internationalized domain names.

Parameters:

  • uri (String, Addressable::URI, #to_str)

    The URI to encode.

  • returning (Class) (defaults to: String)

    The type of object to return. This value may only be set to String or Addressable::URI. All other values are invalid. Defaults to String.

Returns:

  • (String, Addressable::URI)

    The encoded URI. The return type is determined by the returning parameter.



544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
# File 'lib/addressable/uri.rb', line 544

def self.normalized_encode(uri, returning=String)
  begin
    uri = uri.to_str
  rescue NoMethodError, TypeError
    raise TypeError, "Can't convert #{uri.class} into String."
  end if !uri.is_a? String

  if ![String, ::Addressable::URI].include?(returning)
    raise TypeError,
      "Expected Class (String or Addressable::URI), " +
      "got #{returning.inspect}"
  end
  uri_object = uri.kind_of?(self) ? uri : self.parse(uri)
  components = {
    :scheme => self.unencode_component(uri_object.scheme),
    :user => self.unencode_component(uri_object.user),
    :password => self.unencode_component(uri_object.password),
    :host => self.unencode_component(uri_object.host),
    :port => uri_object.port,
    :path => self.unencode_component(uri_object.path),
    :query => self.unencode_component(uri_object.query),
    :fragment => self.unencode_component(uri_object.fragment)
  }
  components.each do |key, value|
    if value != nil
      begin
        components[key] =
          Addressable::IDNA.unicode_normalize_kc(value.to_str)
      rescue ArgumentError
        # Likely a malformed UTF-8 character, skip unicode normalization
        components[key] = value.to_str
      end
    end
  end
  encoded_uri = Addressable::URI.new(
    :scheme => self.encode_component(components[:scheme],
      Addressable::URI::CharacterClasses::SCHEME),
    :user => self.encode_component(components[:user],
      Addressable::URI::CharacterClasses::UNRESERVED),
    :password => self.encode_component(components[:password],
      Addressable::URI::CharacterClasses::UNRESERVED),
    :host => components[:host],
    :port => components[:port],
    :path => self.encode_component(components[:path],
      Addressable::URI::CharacterClasses::PATH),
    :query => self.encode_component(components[:query],
      Addressable::URI::CharacterClasses::QUERY),
    :fragment => self.encode_component(components[:fragment],
      Addressable::URI::CharacterClasses::FRAGMENT)
  )
  if returning == String
    return encoded_uri.to_s
  elsif returning == ::Addressable::URI
    return encoded_uri
  end
end

+ (Addressable::URI) parse(uri)

Returns a URI object based on the parsed string.

Parameters:

  • uri (String, Addressable::URI, #to_str)

    The URI string to parse. No parsing is performed if the object is already an Addressable::URI.

Returns:



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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/addressable/uri.rb', line 83

def self.parse(uri)
  # If we were given nil, return nil.
  return nil unless uri
  # If a URI object is passed, just return itself.
  return uri.dup if uri.kind_of?(self)

  # If a URI object of the Ruby standard library variety is passed,
  # convert it to a string, then parse the string.
  # We do the check this way because we don't want to accidentally
  # cause a missing constant exception to be thrown.
  if uri.class.name =~ /^URI\b/
    uri = uri.to_s
  end

  # Otherwise, convert to a String
  begin
    uri = uri.to_str
  rescue TypeError, NoMethodError
    raise TypeError, "Can't convert #{uri.class} into String."
  end if not uri.is_a? String

  # This Regexp supplied as an example in RFC 3986, and it works great.
  scan = uri.scan(URIREGEX)
  fragments = scan[0]
  scheme = fragments[1]
  authority = fragments[3]
  path = fragments[4]
  query = fragments[6]
  fragment = fragments[8]
  user = nil
  password = nil
  host = nil
  port = nil
  if authority != nil
    # The Regexp above doesn't split apart the authority.
    userinfo = authority[/^([^\[\]]*)@/, 1]
    if userinfo != nil
      user = userinfo.strip[/^([^:]*):?/, 1]
      password = userinfo.strip[/:(.*)$/, 1]
    end
    host = authority.gsub(/^([^\[\]]*)@/, EMPTYSTR).gsub(/:([^:@\[\]]*?)$/, EMPTYSTR)
    port = authority[/:([^:@\[\]]*?)$/, 1]
  end
  if port == EMPTYSTR
    port = nil
  end

  return Addressable::URI.new(
    :scheme => scheme,
    :user => user,
    :password => password,
    :host => host,
    :port => port,
    :path => path,
    :query => query,
    :fragment => fragment
  )
end

+ (Object) port_mapping

Returns a hash of common IP-based schemes and their default port numbers. Adding new schemes to this hash, as necessary, will allow for better URI normalization.



1135
1136
1137
# File 'lib/addressable/uri.rb', line 1135

def self.port_mapping
  PORT_MAPPING
end

+ (String, Addressable::URI) unencode(uri, returning = String) Also known as: unescape, unencode_component, unescape_component

Unencodes any percent encoded characters within a URI component. This method may be used for unencoding either components or full URIs, however, it is recommended to use the unencode_component alias when unencoding components.

Parameters:

  • uri (String, Addressable::URI, #to_str)

    The URI or component to unencode.

  • returning (Class) (defaults to: String)

    The type of object to return. This value may only be set to String or Addressable::URI. All other values are invalid. Defaults to String.

Returns:

  • (String, Addressable::URI)

    The unencoded component or URI. The return type is determined by the returning parameter.



377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/addressable/uri.rb', line 377

def self.unencode(uri, returning=String)
  return nil if uri.nil?

  begin
    uri = uri.to_str
  rescue NoMethodError, TypeError
    raise TypeError, "Can't convert #{uri.class} into String."
  end if !uri.is_a? String
  if ![String, ::Addressable::URI].include?(returning)
    raise TypeError,
      "Expected Class (String or Addressable::URI), " +
      "got #{returning.inspect}"
  end
  result = uri.gsub(/%[0-9a-f]{2}/i) do |sequence|
    sequence[1..3].to_i(16).chr
  end
  result.force_encoding("utf-8") if result.respond_to?(:force_encoding)
  if returning == String
    return result
  elsif returning == ::Addressable::URI
    return ::Addressable::URI.parse(result)
  end
end

Instance Method Details

- (TrueClass, FalseClass) ==(uri)

Returns true if the URI objects are equal. This method normalizes both URIs before doing the comparison.

Parameters:

  • uri (Object)

    The URI to compare.

Returns:

  • (TrueClass, FalseClass)

    true if the URIs are equivalent, false otherwise.



2027
2028
2029
2030
# File 'lib/addressable/uri.rb', line 2027

def ==(uri)
  return false unless uri.kind_of?(URI)
  return self.normalize.to_s == uri.normalize.to_s
end

- (TrueClass, FalseClass) ===(uri)

Returns true if the URI objects are equal. This method normalizes both URIs before doing the comparison, and allows comparison against Strings.

Parameters:

  • uri (Object)

    The URI to compare.

Returns:

  • (TrueClass, FalseClass)

    true if the URIs are equivalent, false otherwise.



2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
# File 'lib/addressable/uri.rb', line 2005

def ===(uri)
  if uri.respond_to?(:normalize)
    uri_string = uri.normalize.to_s
  else
    begin
      uri_string = ::Addressable::URI.parse(uri).normalize.to_s
    rescue InvalidURIError, TypeError
      return false
    end
  end
  return self.normalize.to_s == uri_string
end

- (TrueClass, FalseClass) absolute?

Determines if the URI is absolute.

Returns:

  • (TrueClass, FalseClass)

    true if the URI is absolute. false otherwise.



1674
1675
1676
# File 'lib/addressable/uri.rb', line 1674

def absolute?
  return !relative?
end

- (String) authority

The authority component for this URI. Combines the user, password, host, and port components.

Returns:

  • (String)

    The authority component.



1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
# File 'lib/addressable/uri.rb', line 1036

def authority
  self.host && @authority ||= (begin
    authority = ""
    if self.userinfo != nil
      authority << "#{self.userinfo}@"
    end
    authority << self.host
    if self.port != nil
      authority << ":#{self.port}"
    end
    authority
  end)
end

- (Object) authority=(new_authority)

Sets the authority component for this URI.

Parameters:

  • new_authority (String, #to_str)

    The new authority component.



1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
# File 'lib/addressable/uri.rb', line 1072

def authority=(new_authority)
  if new_authority
    if !new_authority.respond_to?(:to_str)
      raise TypeError, "Can't convert #{new_authority.class} into String."
    end
    new_authority = new_authority.to_str
    new_userinfo = new_authority[/^([^\[\]]*)@/, 1]
    if new_userinfo
      new_user = new_userinfo.strip[/^([^:]*):?/, 1]
      new_password = new_userinfo.strip[/:(.*)$/, 1]
    end
    new_host =
      new_authority.gsub(/^([^\[\]]*)@/, EMPTYSTR).gsub(/:([^:@\[\]]*?)$/, EMPTYSTR)
    new_port =
      new_authority[/:([^:@\[\]]*?)$/, 1]
  end

  # Password assigned first to ensure validity in case of nil
  self.password = defined?(new_password) ? new_password : nil
  self.user = defined?(new_user) ? new_user : nil
  self.host = defined?(new_host) ? new_host : nil
  self.port = defined?(new_port) ? new_port : nil

  # Reset dependant values
  @userinfo = nil
  @normalized_userinfo = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (String) basename

The basename, if any, of the file in the path component.

Returns:

  • (String)

    The path's basename.



1328
1329
1330
1331
# File 'lib/addressable/uri.rb', line 1328

def basename
  # Path cannot be nil
  return File.basename(self.path).gsub(/;[^\/]*$/, EMPTYSTR)
end

- (Object) defer_validation(&block)

This method allows you to make several changes to a URI simultaneously, which separately would cause validation errors, but in conjunction, are valid. The URI will be revalidated as soon as the entire block has been executed.

Parameters:

  • block (Proc)

    A set of operations to perform on a given URI.

Raises:

  • (LocalJumpError)


2177
2178
2179
2180
2181
2182
2183
2184
# File 'lib/addressable/uri.rb', line 2177

def defer_validation(&block)
  raise LocalJumpError, "No block given." unless block
  @validation_deferred = true
  block.call()
  @validation_deferred = false
  validate
  return nil
end

- (Addressable::URI) display_uri

Creates a URI suitable for display to users. If semantic attacks are likely, the application should try to detect these and warn the user. See <a href="RFC">www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>, section 7.6 for more information.

Returns:



1989
1990
1991
1992
1993
# File 'lib/addressable/uri.rb', line 1989

def display_uri
  display_uri = self.normalize
  display_uri.host = ::Addressable::IDNA.to_unicode(display_uri.host)
  return display_uri
end

- (Addressable::URI) dup

Clones the URI object.

Returns:



2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
# File 'lib/addressable/uri.rb', line 2059

def dup
  duplicated_uri = Addressable::URI.new(
    :scheme => self.scheme ? self.scheme.dup : nil,
    :user => self.user ? self.user.dup : nil,
    :password => self.password ? self.password.dup : nil,
    :host => self.host ? self.host.dup : nil,
    :port => self.port,
    :path => self.path ? self.path.dup : nil,
    :query => self.query ? self.query.dup : nil,
    :fragment => self.fragment ? self.fragment.dup : nil
  )
  return duplicated_uri
end

- (TrueClass, FalseClass) eql?(uri)

Returns true if the URI objects are equal. This method does NOT normalize either URI before doing the comparison.

Parameters:

  • uri (Object)

    The URI to compare.

Returns:

  • (TrueClass, FalseClass)

    true if the URIs are equivalent, false otherwise.



2041
2042
2043
2044
# File 'lib/addressable/uri.rb', line 2041

def eql?(uri)
  return false unless uri.kind_of?(URI)
  return self.to_s == uri.to_s
end

- (String) extname

The extname, if any, of the file in the path component. Empty string if there is no extension.

Returns:

  • (String)

    The path's extname.



1338
1339
1340
1341
# File 'lib/addressable/uri.rb', line 1338

def extname
  return nil unless self.path
  return File.extname(self.basename)
end

- (String) fragment

The fragment component for this URI.

Returns:

  • (String)

    The fragment component.



1608
1609
1610
# File 'lib/addressable/uri.rb', line 1608

def fragment
  return instance_variable_defined?(:@fragment) ? @fragment : nil
end

- (Object) fragment=(new_fragment)

Sets the fragment component for this URI.

Parameters:

  • new_fragment (String, #to_str)

    The new fragment component.



1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
# File 'lib/addressable/uri.rb', line 1629

def fragment=(new_fragment)
  if new_fragment && !new_fragment.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_fragment.class} into String."
  end
  @fragment = new_fragment ? new_fragment.to_str : nil

  # Reset dependant values
  @normalized_fragment = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (Addressable::URI) freeze

Freeze URI, initializing instance variables.

Returns:



731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
# File 'lib/addressable/uri.rb', line 731

def freeze
  self.normalized_scheme
  self.normalized_user
  self.normalized_password
  self.normalized_userinfo
  self.normalized_host
  self.normalized_port
  self.normalized_authority
  self.normalized_site
  self.normalized_path
  self.normalized_query
  self.normalized_fragment
  self.hash
  super
end

- (Integer) hash

A hash value that will make a URI equivalent to its normalized form.

Returns:

  • (Integer)

    A hash of the URI.



2051
2052
2053
# File 'lib/addressable/uri.rb', line 2051

def hash
  return @hash ||= (self.to_s.hash * -1)
end

- (String) host Also known as: hostname

The host component for this URI.

Returns:

  • (String)

    The host component.



974
975
976
# File 'lib/addressable/uri.rb', line 974

def host
  return instance_variable_defined?(:@host) ? @host : nil
end

- (Object) host=(new_host) Also known as: hostname=

Sets the host component for this URI.

Parameters:

  • new_host (String, #to_str)

    The new host component.



1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
# File 'lib/addressable/uri.rb', line 1007

def host=(new_host)
  if new_host && !new_host.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_host.class} into String."
  end
  @host = new_host ? new_host.to_str : nil

  # Reset dependant values
  @authority = nil
  @normalized_host = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (Integer) inferred_port

The inferred port component for this URI. This method will normalize to the default port for the URI's scheme if the port isn't explicitly specified in the URI.

Returns:

  • (Integer)

    The inferred port component.



1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
# File 'lib/addressable/uri.rb', line 1193

def inferred_port
  if self.port.to_i == 0
    if self.scheme
      URI.port_mapping[self.scheme.strip.downcase]
    else
      nil
    end
  else
    self.port.to_i
  end
end

- (String) inspect

Returns a String representation of the URI object's state.

Returns:

  • (String)

    The URI object's state, as a String.



2165
2166
2167
# File 'lib/addressable/uri.rb', line 2165

def inspect
  sprintf("#<%s:%#0x URI:%s>", URI.to_s, self.object_id, self.to_s)
end

- (TrueClass, FalseClass) ip_based?

Determines if the scheme indicates an IP-based protocol.

Returns:

  • (TrueClass, FalseClass)

    true if the scheme indicates an IP-based protocol. false otherwise.



1650
1651
1652
1653
1654
1655
1656
# File 'lib/addressable/uri.rb', line 1650

def ip_based?
  if self.scheme
    return URI.ip_based_schemes.include?(
      self.scheme.strip.downcase)
  end
  return false
end

- (Addressable::URI) join(uri) Also known as: +

Joins two URIs together.

Parameters:

Returns:



1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
# File 'lib/addressable/uri.rb', line 1684

def join(uri)
  if !uri.respond_to?(:to_str)
    raise TypeError, "Can't convert #{uri.class} into String."
  end
  if !uri.kind_of?(URI)
    # Otherwise, convert to a String, then parse.
    uri = URI.parse(uri.to_str)
  end
  if uri.to_s.empty?
    return self.dup
  end

  joined_scheme = nil
  joined_user = nil
  joined_password = nil
  joined_host = nil
  joined_port = nil
  joined_path = nil
  joined_query = nil
  joined_fragment = nil

  # Section 5.2.2 of RFC 3986
  if uri.scheme != nil
    joined_scheme = uri.scheme
    joined_user = uri.user
    joined_password = uri.password
    joined_host = uri.host
    joined_port = uri.port
    joined_path = URI.normalize_path(uri.path)
    joined_query = uri.query
  else
    if uri.authority != nil
      joined_user = uri.user
      joined_password = uri.password
      joined_host = uri.host
      joined_port = uri.port
      joined_path = URI.normalize_path(uri.path)
      joined_query = uri.query
    else
      if uri.path == nil || uri.path.empty?
        joined_path = self.path
        if uri.query != nil
          joined_query = uri.query
        else
          joined_query = self.query
        end
      else
        if uri.path[0..0] == SLASH
          joined_path = URI.normalize_path(uri.path)
        else
          base_path = self.path.dup
          base_path = EMPTYSTR if base_path == nil
          base_path = URI.normalize_path(base_path)

          # Section 5.2.3 of RFC 3986
          #
          # Removes the right-most path segment from the base path.
          if base_path =~ /\//
            base_path.gsub!(/\/[^\/]+$/, SLASH)
          else
            base_path = EMPTYSTR
          end

          # If the base path is empty and an authority segment has been
          # defined, use a base path of SLASH
          if base_path.empty? && self.authority != nil
            base_path = SLASH
          end

          joined_path = URI.normalize_path(base_path + uri.path)
        end
        joined_query = uri.query
      end
      joined_user = self.user
      joined_password = self.password
      joined_host = self.host
      joined_port = self.port
    end
    joined_scheme = self.scheme
  end
  joined_fragment = uri.fragment

  return Addressable::URI.new(
    :scheme => joined_scheme,
    :user => joined_user,
    :password => joined_password,
    :host => joined_host,
    :port => joined_port,
    :path => joined_path,
    :query => joined_query,
    :fragment => joined_fragment
  )
end

- (Addressable::URI) join!(uri)

Destructive form of join.

Parameters:

Returns:

See Also:



1787
1788
1789
# File 'lib/addressable/uri.rb', line 1787

def join!(uri)
  replace_self(self.join(uri))
end

- (Addressable::URI) merge(hash)

Merges a URI with a Hash of components. This method has different behavior from join. Any components present in the hash parameter will override the original components. The path component is not treated specially.

Parameters:

Returns:

See Also:

  • Hash#merge


1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
# File 'lib/addressable/uri.rb', line 1802

def merge(hash)
  if !hash.respond_to?(:to_hash)
    raise TypeError, "Can't convert #{hash.class} into Hash."
  end
  hash = hash.to_hash

  if hash.has_key?(:authority)
    if (hash.keys & [:userinfo, :user, :password, :host, :port]).any?
      raise ArgumentError,
        "Cannot specify both an authority and any of the components " +
        "within the authority."
    end
  end
  if hash.has_key?(:userinfo)
    if (hash.keys & [:user, :password]).any?
      raise ArgumentError,
        "Cannot specify both a userinfo and either the user or password."
    end
  end

  uri = Addressable::URI.new
  uri.defer_validation do
    # Bunch of crazy logic required because of the composite components
    # like userinfo and authority.
    uri.scheme =
      hash.has_key?(:scheme) ? hash[:scheme] : self.scheme
    if hash.has_key?(:authority)
      uri.authority =
        hash.has_key?(:authority) ? hash[:authority] : self.authority
    end
    if hash.has_key?(:userinfo)
      uri.userinfo =
        hash.has_key?(:userinfo) ? hash[:userinfo] : self.userinfo
    end
    if !hash.has_key?(:userinfo) && !hash.has_key?(:authority)
      uri.user =
        hash.has_key?(:user) ? hash[:user] : self.user
      uri.password =
        hash.has_key?(:password) ? hash[:password] : self.password
    end
    if !hash.has_key?(:authority)
      uri.host =
        hash.has_key?(:host) ? hash[:host] : self.host
      uri.port =
        hash.has_key?(:port) ? hash[:port] : self.port
    end
    uri.path =
      hash.has_key?(:path) ? hash[:path] : self.path
    uri.query =
      hash.has_key?(:query) ? hash[:query] : self.query
    uri.fragment =
      hash.has_key?(:fragment) ? hash[:fragment] : self.fragment
  end

  return uri
end

- (Addressable::URI) merge!(uri)

Destructive form of merge.

Parameters:

Returns:

See Also:



1867
1868
1869
# File 'lib/addressable/uri.rb', line 1867

def merge!(uri)
  replace_self(self.merge(uri))
end

- (Addressable::URI) normalize

Returns a normalized URI object.

NOTE: This method does not attempt to fully conform to specifications. It exists largely to correct other people's failures to read the specifications, and also to deal with caching issues since several different URIs may represent the same resource and should not be cached multiple times.

Returns:



1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
# File 'lib/addressable/uri.rb', line 1952

def normalize
  # This is a special exception for the frequently misused feed
  # URI scheme.
  if normalized_scheme == "feed"
    if self.to_s =~ /^feed:\/*http:\/*/
      return URI.parse(
        self.to_s[/^feed:\/*(http:\/*.*)/, 1]
      ).normalize
    end
  end

  return Addressable::URI.new(
    :scheme => normalized_scheme,
    :authority => normalized_authority,
    :path => normalized_path,
    :query => normalized_query,
    :fragment => normalized_fragment
  )
end

- (Addressable::URI) normalize!

Destructively normalizes this URI object.

Returns:

See Also:



1978
1979
1980
# File 'lib/addressable/uri.rb', line 1978

def normalize!
  replace_self(self.normalize)
end

- (String) normalized_authority

The authority component for this URI, normalized.

Returns:

  • (String)

    The authority component, normalized.



1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
# File 'lib/addressable/uri.rb', line 1054

def normalized_authority
  self.authority && @normalized_authority ||= (begin
    authority = ""
    if self.normalized_userinfo != nil
      authority << "#{self.normalized_userinfo}@"
    end
    authority << self.normalized_host
    if self.normalized_port != nil
      authority << ":#{self.normalized_port}"
    end
    authority
  end)
end

- (String) normalized_fragment

The fragment component for this URI, normalized.

Returns:

  • (String)

    The fragment component, normalized.



1616
1617
1618
1619
1620
1621
1622
1623
# File 'lib/addressable/uri.rb', line 1616

def normalized_fragment
  self.fragment && @normalized_fragment ||= (begin
    Addressable::URI.normalize_component(
      self.fragment.strip,
      Addressable::URI::CharacterClasses::FRAGMENT
    )
  end)
end

- (String) normalized_host

The host component for this URI, normalized.

Returns:

  • (String)

    The host component, normalized.



982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
# File 'lib/addressable/uri.rb', line 982

def normalized_host
  self.host && @normalized_host ||= (begin
    if self.host != nil
      if !self.host.strip.empty?
        result = ::Addressable::IDNA.to_ascii(
          URI.unencode_component(self.host.strip.downcase)
        )
        if result[-1..-1] == "."
          # Trailing dots are unnecessary
          result = result[0...-1]
        end
        result
      else
        EMPTYSTR
      end
    else
      nil
    end
  end)
end

- (String) normalized_password

The password component for this URI, normalized.

Returns:

  • (String)

    The password component, normalized.



862
863
864
865
866
867
868
869
870
871
872
873
874
# File 'lib/addressable/uri.rb', line 862

def normalized_password
  self.password && @normalized_password ||= (begin
    if self.normalized_scheme =~ /https?/ && self.password.strip.empty? &&
        (!self.user || self.user.strip.empty?)
      nil
    else
      Addressable::URI.normalize_component(
        self.password.strip,
        Addressable::URI::CharacterClasses::UNRESERVED
      )
    end
  end)
end

- (String) normalized_path

The path component for this URI, normalized.

Returns:

  • (String)

    The path component, normalized.



1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
# File 'lib/addressable/uri.rb', line 1280

def normalized_path
  @normalized_path ||= (begin
    path = self.path.to_s
    if self.scheme == nil && path =~ NORMPATH
      # Relative paths with colons in the first segment are ambiguous.
      path = path.sub(":", "%2F")
    end
    # String#split(delimeter, -1) uses the more strict splitting behavior
    # found by default in Python.
    result = (path.strip.split(SLASH, -1).map do |segment|
      Addressable::URI.normalize_component(
        segment,
        Addressable::URI::CharacterClasses::PCHAR
      )
    end).join(SLASH)

    result = URI.normalize_path(result)
    if result.empty? &&
        ["http", "https", "ftp", "tftp"].include?(self.normalized_scheme)
      result = SLASH
    end
    result
  end)
end

- (Integer) normalized_port

The port component for this URI, normalized.

Returns:

  • (Integer)

    The port component, normalized.



1153
1154
1155
1156
1157
1158
1159
# File 'lib/addressable/uri.rb', line 1153

def normalized_port
  if URI.port_mapping[self.normalized_scheme] == self.port
    nil
  else
    self.port
  end
end

- (String) normalized_query

The query component for this URI, normalized.

Returns:

  • (String)

    The query component, normalized.



1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
# File 'lib/addressable/uri.rb', line 1355

def normalized_query
  self.query && @normalized_query ||= (begin
    (self.query.split("&", -1).map do |pair|
      Addressable::URI.normalize_component(
        pair,
        Addressable::URI::CharacterClasses::QUERY.sub("\\&", "")
      )
    end).join("&")
  end)
end

- (String) normalized_scheme

The scheme component for this URI, normalized.

Returns:

  • (String)

    The scheme component, normalized.



759
760
761
762
763
764
765
766
767
768
769
770
# File 'lib/addressable/uri.rb', line 759

def normalized_scheme
  self.scheme && @normalized_scheme ||= (begin
    if self.scheme =~ /^\s*ssh\+svn\s*$/i
      "svn+ssh"
    else
      Addressable::URI.normalize_component(
        self.scheme.strip.downcase,
        Addressable::URI::CharacterClasses::SCHEME
      )
    end
  end)
end

- (String) normalized_site

The normalized combination of components that represent a site. Combines the scheme, user, password, host, and port components. Primarily useful for HTTP and HTTPS.

For example, "http://example.com/path?query" would have a site value of "http://example.com".

Returns:

  • (String)

    The normalized components that identify a site.



1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
# File 'lib/addressable/uri.rb', line 1232

def normalized_site
  self.site && @normalized_site ||= (begin
    site_string = ""
    if self.normalized_scheme != nil
      site_string << "#{self.normalized_scheme}:"
    end
    if self.normalized_authority != nil
      site_string << "//#{self.normalized_authority}"
    end
    site_string
  end)
end

- (String) normalized_user

The user component for this URI, normalized.

Returns:

  • (String)

    The user component, normalized.



809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'lib/addressable/uri.rb', line 809

def normalized_user
  self.user && @normalized_user ||= (begin
    if normalized_scheme =~ /https?/ && self.user.strip.empty? &&
        (!self.password || self.password.strip.empty?)
      nil
    else
      Addressable::URI.normalize_component(
        self.user.strip,
        Addressable::URI::CharacterClasses::UNRESERVED
      )
    end
  end)
end

- (String) normalized_userinfo

The userinfo component for this URI, normalized.

Returns:

  • (String)

    The userinfo component, normalized.



926
927
928
929
930
931
932
933
934
935
936
937
938
# File 'lib/addressable/uri.rb', line 926

def normalized_userinfo
  self.userinfo && @normalized_userinfo ||= (begin
    current_user = self.normalized_user
    current_password = self.normalized_password
    if !current_user && !current_password
      nil
    elsif current_user && current_password
      "#{current_user}:#{current_password}"
    elsif current_user && !current_password
      "#{current_user}"
    end
  end)
end

- (Addressable::URI) omit(*components)

Omits components from a URI.

Examples:

uri = Addressable::URI.parse("http://example.com/path?query")
#=> #<Addressable::URI:0xcc5e7a URI:http://example.com/path?query>
uri.omit(:scheme, :authority)
#=> #<Addressable::URI:0xcc4d86 URI:/path?query>

Parameters:

  • *components (Symbol)

    The components to be omitted.

Returns:



2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
# File 'lib/addressable/uri.rb', line 2085

def omit(*components)
  invalid_components = components - [
    :scheme, :user, :password, :userinfo, :host, :port, :authority,
    :path, :query, :fragment
  ]
  unless invalid_components.empty?
    raise ArgumentError,
      "Invalid component names: #{invalid_components.inspect}."
  end
  duplicated_uri = self.dup
  duplicated_uri.defer_validation do
    components.each do |component|
      duplicated_uri.send((component.to_s + "=").to_sym, nil)
    end
    duplicated_uri.user = duplicated_uri.normalized_user
  end
  duplicated_uri
end

- (Addressable::URI) omit!(*components)

Destructive form of omit.

Parameters:

  • *components (Symbol)

    The components to be omitted.

Returns:

See Also:



2112
2113
2114
# File 'lib/addressable/uri.rb', line 2112

def omit!(*components)
  replace_self(self.omit(*components))
end

- (String) origin

The origin for this URI, serialized to ASCII, as per draft-ietf-websec-origin-00, section 5.2.

Returns:

  • (String)

    The serialized origin.



1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
# File 'lib/addressable/uri.rb', line 1110

def origin
  return (if self.scheme && self.authority
    if self.normalized_port
      (
        "#{self.normalized_scheme}://#{self.normalized_host}" +
        ":#{self.normalized_port}"
      )
    else
      "#{self.normalized_scheme}://#{self.normalized_host}"
    end
  else
    "null"
  end)
end

- (String) password

The password component for this URI.

Returns:

  • (String)

    The password component.



854
855
856
# File 'lib/addressable/uri.rb', line 854

def password
  return instance_variable_defined?(:@password) ? @password : nil
end

- (Object) password=(new_password)

Sets the password component for this URI.

Parameters:

  • new_password (String, #to_str)

    The new password component.



880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
# File 'lib/addressable/uri.rb', line 880

def password=(new_password)
  if new_password && !new_password.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_password.class} into String."
  end
  @password = new_password ? new_password.to_str : nil

  # You can't have a nil user with a non-nil password
  @password ||= nil
  @user ||= nil
  if @password != nil
    @user = EMPTYSTR if @user.nil?
  end

  # Reset dependant values
  @userinfo = nil
  @normalized_userinfo = nil
  @authority = nil
  @normalized_password = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (String) path

The path component for this URI.

Returns:

  • (String)

    The path component.



1271
1272
1273
# File 'lib/addressable/uri.rb', line 1271

def path
  return instance_variable_defined?(:@path) ? @path : EMPTYSTR
end

- (Object) path=(new_path)

Sets the path component for this URI.

Parameters:

  • new_path (String, #to_str)

    The new path component.



1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
# File 'lib/addressable/uri.rb', line 1309

def path=(new_path)
  if new_path && !new_path.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_path.class} into String."
  end
  @path = (new_path || EMPTYSTR).to_str
  if !@path.empty? && @path[0..0] != SLASH && host != nil
    @path = "/#{@path}"
  end

  # Reset dependant values
  @normalized_path = nil
  @uri_string = nil
  @hash = nil
end

- (Integer) port

The port component for this URI. This is the port number actually given in the URI. This does not infer port numbers from default values.

Returns:

  • (Integer)

    The port component.



1145
1146
1147
# File 'lib/addressable/uri.rb', line 1145

def port
  return instance_variable_defined?(:@port) ? @port : nil
end

- (Object) port=(new_port)

Sets the port component for this URI.

Parameters:

  • new_port (String, Integer, #to_s)

    The new port component.



1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
# File 'lib/addressable/uri.rb', line 1165

def port=(new_port)
  if new_port != nil && new_port.respond_to?(:to_str)
    new_port = Addressable::URI.unencode_component(new_port.to_str)
  end
  if new_port != nil && !(new_port.to_s =~ /^\d+$/)
    raise InvalidURIError,
      "Invalid port number: #{new_port.inspect}"
  end

  @port = new_port.to_s.to_i
  @port = nil if @port == 0

  # Reset dependant values
  @authority = nil
  @normalized_port = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (String) query

The query component for this URI.

Returns:

  • (String)

    The query component.



1347
1348
1349
# File 'lib/addressable/uri.rb', line 1347

def query
  return instance_variable_defined?(:@query) ? @query : nil
end

- (Object) query=(new_query)

Sets the query component for this URI.

Parameters:

  • new_query (String, #to_str)

    The new query component.



1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
# File 'lib/addressable/uri.rb', line 1370

def query=(new_query)
  if new_query && !new_query.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_query.class} into String."
  end
  @query = new_query ? new_query.to_str : nil

  # Reset dependant values
  @normalized_query = nil
  @uri_string = nil
  @hash = nil
end

- (Hash, Array) query_values(options = {})

Converts the query component to a Hash value.

Examples:

Addressable::URI.parse("?one=1&two=2&three=3").query_values
#=> {"one" => "1", "two" => "2", "three" => "3"}
Addressable::URI.parse("?one[two][three]=four").query_values
#=> {"one" => {"two" => {"three" => "four"}}}
Addressable::URI.parse("?one.two.three=four").query_values(
  :notation => :dot
)
#=> {"one" => {"two" => {"three" => "four"}}}
Addressable::URI.parse("?one[two][three]=four").query_values(
  :notation => :flat
)
#=> {"one[two][three]" => "four"}
Addressable::URI.parse("?one.two.three=four").query_values(
  :notation => :flat
)
#=> {"one.two.three" => "four"}
Addressable::URI.parse(
  "?one[two][three][]=four&one[two][three][]=five"
).query_values
#=> {"one" => {"two" => {"three" => ["four", "five"]}}}
Addressable::URI.parse(
  "?one=two&one=three").query_values(:notation => :flat_array)
#=> [['one', 'two'], ['one', 'three']]

Parameters:

  • [Symbol] (Hash)

    a customizable set of options

Returns:

  • (Hash, Array)

    The query string parsed as a Hash or Array object.



1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
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
# File 'lib/addressable/uri.rb', line 1416

def query_values(options={})
  defaults = {:notation => :subscript}
  options = defaults.merge(options)
  if ![:flat, :dot, :subscript, :flat_array].include?(options[:notation])
    raise ArgumentError,
      "Invalid notation. Must be one of: " +
      "[:flat, :dot, :subscript, :flat_array]."
  end
  dehash = lambda do |hash|
    hash.each do |(key, value)|
      if value.kind_of?(Hash)
        hash[key] = dehash.call(value)
      end
    end
    if hash != {} && hash.keys.all? { |key| key =~ /^\d+$/ }
      hash.sort.inject([]) do |accu, (_, value)|
        accu << value; accu
      end
    else
      hash
    end
  end
  return nil if self.query == nil
  empty_accumulator = :flat_array == options[:notation] ? [] : {}
  return ((self.query.split("&").map do |pair|
    pair.split("=", 2) if pair && !pair.empty?
  end).compact.inject(empty_accumulator.dup) do |accumulator, (key, value)|
    value = true if value.nil?
    key = URI.unencode_component(key)
    if value != true
      value = URI.unencode_component(value.gsub(/\+/, " "))
    end
    if options[:notation] == :flat
      if accumulator[key]
        raise ArgumentError, "Key was repeated: #{key.inspect}"
      end
      accumulator[key] = value
    elsif options[:notation] == :flat_array
      accumulator << [key, value]
    else
      if options[:notation] == :dot
        array_value = false
        subkeys = key.split(".")
      elsif options[:notation] == :subscript
        array_value = !!(key =~ /\[\]$/)
        subkeys = key.split(/[\[\]]+/)
      end
      current_hash = accumulator
      for i in 0...(subkeys.size - 1)
        subkey = subkeys[i]
        current_hash[subkey] = {} unless current_hash[subkey]
        current_hash = current_hash[subkey]
      end
      if array_value
        current_hash[subkeys.last] = [] unless current_hash[subkeys.last]
        current_hash[subkeys.last] << value
      else
        current_hash[subkeys.last] = value
      end
    end
    accumulator
  end).inject(empty_accumulator.dup) do |accumulator, (key, value)|
    if options[:notation] == :flat_array
      accumulator << [key, value]
    else
      accumulator[key] = value.kind_of?(Hash) ? dehash.call(value) : value
    end
    accumulator
  end
end

- (Object) query_values=(new_query_values)

Sets the query component for this URI from a Hash object. This method produces a query string using the :subscript notation. An empty Hash will result in a nil query.

Parameters:

  • new_query_values (Hash, #to_hash, Array)

    The new query values.



1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
# File 'lib/addressable/uri.rb', line 1493

def query_values=(new_query_values)
  if new_query_values == nil
    self.query = nil
    return nil
  end

  if !new_query_values.is_a?(Array)
    if !new_query_values.respond_to?(:to_hash)
      raise TypeError,
        "Can't convert #{new_query_values.class} into Hash."
    end
    new_query_values = new_query_values.to_hash
    new_query_values = new_query_values.map do |key, value|
      key = key.to_s if key.kind_of?(Symbol)
      [key, value]
    end
    # Useful default for OAuth and caching.
    # Only to be used for non-Array inputs. Arrays should preserve order.
    new_query_values.sort!
  end

  ##
  # Joins and converts parent and value into a properly encoded and
  # ordered URL query.
  #
  # @private
  # @param [String] parent an URI encoded component.
  # @param [Array, Hash, Symbol, #to_str] value
  #
  # @return [String] a properly escaped and ordered URL query.
  to_query = lambda do |parent, value|
    if value.is_a?(Hash)
      value = value.map do |key, val|
        [
          URI.encode_component(key, CharacterClasses::UNRESERVED),
          val
        ]
      end
      value.sort!
      buffer = ""
      value.each do |key, val|
        new_parent = "#{parent}[#{key}]"
        buffer << "#{to_query.call(new_parent, val)}&"
      end
      return buffer.chop
    elsif value.is_a?(Array)
      buffer = ""
      value.each_with_index do |val, i|
        new_parent = "#{parent}[#{i}]"
        buffer << "#{to_query.call(new_parent, val)}&"
      end
      return buffer.chop
    elsif value == true
      return parent
    else
      encoded_value = URI.encode_component(
        value, CharacterClasses::UNRESERVED
      )
      return "#{parent}=#{encoded_value}"
    end
  end

  # new_query_values have form [['key1', 'value1'], ['key2', 'value2']]
  buffer = ""
  new_query_values.each do |parent, value|
    encoded_parent = URI.encode_component(
      parent, CharacterClasses::UNRESERVED
    )
    buffer << "#{to_query.call(encoded_parent, value)}&"
  end
  self.query = buffer.chop
end

- (TrueClass, FalseClass) relative?

Determines if the URI is relative.

Returns:

  • (TrueClass, FalseClass)

    true if the URI is relative. false otherwise.



1664
1665
1666
# File 'lib/addressable/uri.rb', line 1664

def relative?
  return self.scheme.nil?
end

- (String) request_uri

The HTTP request URI for this URI. This is the path and the query string.

Returns:

  • (String)

    The request URI required for an HTTP request.



1571
1572
1573
1574
1575
1576
1577
# File 'lib/addressable/uri.rb', line 1571

def request_uri
  return nil if self.absolute? && self.scheme !~ /^https?$/
  return (
    (!self.path.empty? ? self.path : SLASH) +
    (self.query ? "?#{self.query}" : EMPTYSTR)
  )
end

- (Object) request_uri=(new_request_uri)

Sets the HTTP request URI for this URI.

Parameters:

  • new_request_uri (String, #to_str)

    The new HTTP request URI.



1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
# File 'lib/addressable/uri.rb', line 1583

def request_uri=(new_request_uri)
  if !new_request_uri.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_request_uri.class} into String."
  end
  if self.absolute? && self.scheme !~ /^https?$/
    raise InvalidURIError,
      "Cannot set an HTTP request URI for a non-HTTP URI."
  end
  new_request_uri = new_request_uri.to_str
  path_component = new_request_uri[/^([^\?]*)\?(?:.*)$/, 1]
  query_component = new_request_uri[/^(?:[^\?]*)\?(.*)$/, 1]
  path_component = path_component.to_s
  path_component = (!path_component.empty? ? path_component : SLASH)
  self.path = path_component
  self.query = query_component

  # Reset dependant values
  @uri_string = nil
  @hash = nil
end

- (Addressable::URI) route_from(uri)

Returns the shortest normalized relative form of this URI that uses the supplied URI as a base for resolution. Returns an absolute URI if necessary. This is effectively the opposite of route_to.

Parameters:

Returns:

  • (Addressable::URI)

    The normalized relative URI that is equivalent to the original URI.



1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
# File 'lib/addressable/uri.rb', line 1880

def route_from(uri)
  uri = URI.parse(uri).normalize
  normalized_self = self.normalize
  if normalized_self.relative?
    raise ArgumentError, "Expected absolute URI, got: #{self.to_s}"
  end
  if uri.relative?
    raise ArgumentError, "Expected absolute URI, got: #{uri.to_s}"
  end
  if normalized_self == uri
    return Addressable::URI.parse("##{normalized_self.fragment}")
  end
  components = normalized_self.to_hash
  if normalized_self.scheme == uri.scheme
    components[:scheme] = nil
    if normalized_self.authority == uri.authority
      components[:user] = nil
      components[:password] = nil
      components[:host] = nil
      components[:port] = nil
      if normalized_self.path == uri.path
        components[:path] = nil
        if normalized_self.query == uri.query
          components[:query] = nil
        end
      else
        if uri.path != SLASH
          components[:path].gsub!(
            Regexp.new("^" + Regexp.escape(uri.path)), EMPTYSTR)
        end
      end
    end
  end
  # Avoid network-path references.
  if components[:host] != nil
    components[:scheme] = normalized_self.scheme
  end
  return Addressable::URI.new(
    :scheme => components[:scheme],
    :user => components[:user],
    :password => components[:password],
    :host => components[:host],
    :port => components[:port],
    :path => components[:path],
    :query => components[:query],
    :fragment => components[:fragment]
  )
end

- (Addressable::URI) route_to(uri)

Returns the shortest normalized relative form of the supplied URI that uses this URI as a base for resolution. Returns an absolute URI if necessary. This is effectively the opposite of route_from.

Parameters:

Returns:

  • (Addressable::URI)

    The normalized relative URI that is equivalent to the supplied URI.



1938
1939
1940
# File 'lib/addressable/uri.rb', line 1938

def route_to(uri)
  return URI.parse(uri).route_from(self)
end

- (String) scheme

The scheme component for this URI.

Returns:

  • (String)

    The scheme component.



751
752
753
# File 'lib/addressable/uri.rb', line 751

def scheme
  return instance_variable_defined?(:@scheme) ? @scheme : nil
end

- (Object) scheme=(new_scheme)

Sets the scheme component for this URI.

Parameters:

  • new_scheme (String, #to_str)

    The new scheme component.



776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
# File 'lib/addressable/uri.rb', line 776

def scheme=(new_scheme)
  if new_scheme && !new_scheme.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_scheme.class} into String."
  elsif new_scheme
    new_scheme = new_scheme.to_str
  end
  if new_scheme && new_scheme !~ /[a-z][a-z0-9\.\+\-]*/i
    raise InvalidURIError, "Invalid scheme format."
  end
  @scheme = new_scheme
  @scheme = nil if @scheme.to_s.strip.empty?

  # Reset dependant values
  @normalized_scheme = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (String) site

The combination of components that represent a site. Combines the scheme, user, password, host, and port components. Primarily useful for HTTP and HTTPS.

For example, "http://example.com/path?query" would have a site value of "http://example.com".

Returns:

  • (String)

    The components that identify a site.



1214
1215
1216
1217
1218
1219
1220
1221
# File 'lib/addressable/uri.rb', line 1214

def site
  (self.scheme || self.authority) && @site ||= (begin
    site_string = ""
    site_string << "#{self.scheme}:" if self.scheme != nil
    site_string << "//#{self.authority}" if self.authority != nil
    site_string
  end)
end

- (Object) site=(new_site)

Sets the site value for this URI.

Parameters:

  • new_site (String, #to_str)

    The new site value.



1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
# File 'lib/addressable/uri.rb', line 1249

def site=(new_site)
  if new_site
    if !new_site.respond_to?(:to_str)
      raise TypeError, "Can't convert #{new_site.class} into String."
    end
    new_site = new_site.to_str
    # These two regular expressions derived from the primary parsing
    # expression
    self.scheme = new_site[/^(?:([^:\/?#]+):)?(?:\/\/(?:[^\/?#]*))?$/, 1]
    self.authority = new_site[
      /^(?:(?:[^:\/?#]+):)?(?:\/\/([^\/?#]*))?$/, 1
    ]
  else
    self.scheme = nil
    self.authority = nil
  end
end

- (Hash) to_hash

Returns a Hash of the URI components.

Returns:

  • (Hash)

    The URI as a Hash of components.



2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
# File 'lib/addressable/uri.rb', line 2148

def to_hash
  return {
    :scheme => self.scheme,
    :user => self.user,
    :password => self.password,
    :host => self.host,
    :port => self.port,
    :path => self.path,
    :query => self.query,
    :fragment => self.fragment
  }
end

- (String) to_s Also known as: to_str

Converts the URI to a String.

Returns:

  • (String)

    The URI's String representation.



2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
# File 'lib/addressable/uri.rb', line 2120

def to_s
  if self.scheme == nil && self.path != nil && !self.path.empty? &&
      self.path =~ NORMPATH
    raise InvalidURIError,
      "Cannot assemble URI string with ambiguous path: '#{self.path}'"
  end
  @uri_string ||= (begin
    uri_string = ""
    uri_string << "#{self.scheme}:" if self.scheme != nil
    uri_string << "//#{self.authority}" if self.authority != nil
    uri_string << self.path.to_s
    uri_string << "?#{self.query}" if self.query != nil
    uri_string << "##{self.fragment}" if self.fragment != nil
    if uri_string.respond_to?(:force_encoding)
      uri_string.force_encoding(Encoding::UTF_8)
    end
    uri_string
  end)
end

- (String) user

The user component for this URI.

Returns:

  • (String)

    The user component.



801
802
803
# File 'lib/addressable/uri.rb', line 801

def user
  return instance_variable_defined?(:@user) ? @user : nil
end

- (Object) user=(new_user)

Sets the user component for this URI.

Parameters:

  • new_user (String, #to_str)

    The new user component.



827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/addressable/uri.rb', line 827

def user=(new_user)
  if new_user && !new_user.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_user.class} into String."
  end
  @user = new_user ? new_user.to_str : nil

  # You can't have a nil user with a non-nil password
  if password != nil
    @user = EMPTYSTR if @user.nil?
  end

  # Reset dependant values
  @userinfo = nil
  @normalized_userinfo = nil
  @authority = nil
  @normalized_user = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end

- (String) userinfo

The userinfo component for this URI. Combines the user and password components.

Returns:

  • (String)

    The userinfo component.



910
911
912
913
914
915
916
917
918
919
920
# File 'lib/addressable/uri.rb', line 910

def userinfo
  current_user = self.user
  current_password = self.password
  (current_user || current_password) && @userinfo ||= (begin
    if current_user && current_password
      "#{current_user}:#{current_password}"
    elsif current_user && !current_password
      "#{current_user}"
    end
  end)
end

- (Object) userinfo=(new_userinfo)

Sets the userinfo component for this URI.

Parameters:

  • new_userinfo (String, #to_str)

    The new userinfo component.



944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
# File 'lib/addressable/uri.rb', line 944

def userinfo=(new_userinfo)
  if new_userinfo && !new_userinfo.respond_to?(:to_str)
    raise TypeError, "Can't convert #{new_userinfo.class} into String."
  end
  new_user, new_password = if new_userinfo
    [
      new_userinfo.to_str.strip[/^(.*):/, 1],
      new_userinfo.to_str.strip[/:(.*)$/, 1]
    ]
  else
    [nil, nil]
  end

  # Password assigned first to ensure validity in case of nil
  self.password = new_password
  self.user = new_user

  # Reset dependant values
  @authority = nil
  @uri_string = nil
  @hash = nil

  # Ensure we haven't created an invalid URI
  validate()
end