| Class | Addressable::URI |
| In: |
lib/addressable/uri.rb
|
| Parent: | Object |
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>.
| encode_component | -> | encode_component |
| unencode | -> | unescape |
| unencode | -> | unencode_component |
| unencode | -> | unescape_component |
| encode | -> | escape |
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.
@param [String, Addressable::URI, to_str] path
Typically a <tt>String</tt> path to a file or directory, but will return a sensible return value if an absolute URI is supplied instead.
@return [Addressable::URI]
The parsed file scheme URI or the original URI if some other URI scheme was provided.
@example
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/"
# File lib/addressable/uri.rb, line 233
233: def self.convert_path(path)
234: # If we were given nil, return nil.
235: return nil unless path
236: # If a URI object is passed, just return itself.
237: return path if path.kind_of?(self)
238: if !path.respond_to?(:to_str)
239: raise TypeError, "Can't convert #{path.class} into String."
240: end
241: # Otherwise, convert to a String
242: path = path.to_str.strip
243:
244: path.gsub!(/^file:\/?\/?/, "") if path =~ /^file:\/?\/?/
245: path = "/" + path if path =~ /^([a-zA-Z])(\||:)/
246: uri = self.parse(path)
247:
248: if uri.scheme == nil
249: # Adjust windows-style uris
250: uri.path.gsub!(/^\/?([a-zA-Z])\|(\\|\/)/, "/\\1:/")
251: uri.path.gsub!(/\\/, "/")
252: if File.exists?(uri.path) &&
253: File.stat(uri.path).directory?
254: uri.path.gsub!(/\/$/, "")
255: uri.path = uri.path + '/'
256: end
257:
258: # If the path is absolute, set the scheme and host.
259: if uri.path =~ /^\//
260: uri.scheme = "file"
261: uri.host = ""
262: end
263: uri.normalize!
264: end
265:
266: return uri
267: end
Percent encodes any special characters in the URI.
@param [String, Addressable::URI, to_str] uri
The URI to encode.
@param [Class] returning
The type of object to return. This value may only be set to <tt>String</tt> or <tt>Addressable::URI</tt>. All other values are invalid. Defaults to <tt>String</tt>.
@return [String, Addressable::URI]
The encoded URI. The return type is determined by the <tt>returning</tt> parameter.
# File lib/addressable/uri.rb, line 1026
1026: def self.encode(uri, returning=String)
1027: return nil if uri.nil?
1028: if !uri.respond_to?(:to_str)
1029: raise TypeError, "Can't convert #{uri.class} into String."
1030: end
1031: if ![String, ::Addressable::URI].include?(returning)
1032: raise TypeError,
1033: "Expected String or Addressable::URI, got #{returning.inspect}"
1034: end
1035: uri_object = uri.kind_of?(self) ? uri : self.parse(uri.to_str)
1036: encoded_uri = Addressable::URI.new(
1037: :scheme => self.encode_component(uri_object.scheme,
1038: Addressable::URI::CharacterClasses::SCHEME),
1039: :authority => self.encode_component(uri_object.authority,
1040: Addressable::URI::CharacterClasses::AUTHORITY),
1041: :path => self.encode_component(uri_object.path,
1042: Addressable::URI::CharacterClasses::PATH),
1043: :query => self.encode_component(uri_object.query,
1044: Addressable::URI::CharacterClasses::QUERY),
1045: :fragment => self.encode_component(uri_object.fragment,
1046: Addressable::URI::CharacterClasses::FRAGMENT)
1047: )
1048: if returning == String
1049: return encoded_uri.to_s
1050: elsif returning == ::Addressable::URI
1051: return encoded_uri
1052: end
1053: end
Percent encodes a URI component.
@param [String, to_str] component The URI component to encode.
@param [String, Regexp] character_class
The characters which are not percent encoded. If a <tt>String</tt> is passed, the <tt>String</tt> must be formatted as a regular expression character class. (Do not include the surrounding square brackets.) For example, <tt>"b-zB-Z0-9"</tt> would cause everything but the letters 'b' through 'z' and the numbers '0' through '9' to be percent encoded. If a <tt>Regexp</tt> is passed, the value <tt>/[^b-zB-Z0-9]/</tt> would have the same effect. A set of useful <tt>String</tt> values may be found in the <tt>Addressable::URI::CharacterClasses</tt> module. The default value is the reserved plus unreserved character classes specified in <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
@return [String] The encoded component.
@example
Addressable::URI.encode_component("simple/example", "b-zB-Z0-9")
=> "simple%2Fex%61mple"
Addressable::URI.encode_component("simple/example", /[^b-zB-Z0-9]/)
=> "simple%2Fex%61mple"
Addressable::URI.encode_component(
"simple/example", Addressable::URI::CharacterClasses::UNRESERVED
)
=> "simple%2Fexample"
# File lib/addressable/uri.rb, line 946
946: def self.encode_component(component, character_class=
947: CharacterClasses::RESERVED + CharacterClasses::UNRESERVED)
948: return nil if component.nil?
949: if !component.respond_to?(:to_str)
950: raise TypeError, "Can't convert #{component.class} into String."
951: end
952: component = component.to_str
953: if ![String, Regexp].include?(character_class.class)
954: raise TypeError,
955: "Expected String or Regexp, got #{character_class.inspect}"
956: end
957: if character_class.kind_of?(String)
958: character_class = /[^#{character_class}]/
959: end
960: return component.gsub(character_class) do |sequence|
961: (sequence.unpack('C*').map { |c| "%#{c.to_s(16).upcase}" }).join("")
962: end
963: end
Expands a URI template into a full URI.
@param [String, to_str] pattern The URI template pattern. @param [Hash] mapping The mapping that corresponds to the pattern. @param [validate, transform] processor
An optional processor object may be supplied. The object should respond to either the <tt>validate</tt> or <tt>transform</tt> messages or both. Both the <tt>validate</tt> and <tt>transform</tt> methods should take two parameters: <tt>name</tt> and <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt> or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid, <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception will be raised if the value is invalid. The <tt>transform</tt> method should return the transformed variable value as a <tt>String</tt>.
@return [Addressable::URI] The expanded URI template.
@example
class ExampleProcessor
def self.validate(name, value)
return !!(value =~ /^[\w ]+$/) if name == "query"
return true
end
def self.transform(name, value)
return value.gsub(/ /, "+") if name == "query"
return value
end
end
Addressable::URI.expand_template(
"http://example.com/search/{query}/",
{"query" => "an example search query"},
ExampleProcessor
).to_s
#=> "http://example.com/search/an+example+search+query/"
Addressable::URI.expand_template(
"http://example.com/search/{-list|+|query}/",
{"query" => "an example search query".split(" ")}
).to_s
#=> "http://example.com/search/an+example+search+query/"
Addressable::URI.expand_template(
"http://example.com/search/{query}/",
{"query" => "bogus!"},
ExampleProcessor
).to_s
#=> Addressable::URI::InvalidTemplateValueError
# File lib/addressable/uri.rb, line 320
320: def self.expand_template(pattern, mapping, processor=nil)
321:
322: # FIXME: MUST REFACTOR!!!
323:
324: result = pattern.dup
325:
326: reserved = Addressable::URI::CharacterClasses::RESERVED
327: unreserved = Addressable::URI::CharacterClasses::UNRESERVED
328: anything = reserved + unreserved
329: operator_expansion =
330: /\{-([a-zA-Z]+)\|([#{anything}]+)\|([#{anything}]+)\}/
331: variable_expansion = /\{([#{anything}]+?)(=([#{anything}]+))?\}/
332:
333: transformed_mapping = mapping.inject({}) do |accu, pair|
334: name, value = pair
335: unless value.respond_to?(:to_ary) || value.respond_to?(:to_str)
336: raise TypeError,
337: "Can't convert #{value.class} into String or Array."
338: end
339: transformed_value =
340: value.respond_to?(:to_ary) ? value.to_ary : value.to_str
341:
342: # Handle percent escaping, and unicode normalization
343: if transformed_value.kind_of?(Array)
344: transformed_value.map! do |value|
345: self.encode_component(
346: Addressable::IDNA.unicode_normalize_kc(value),
347: Addressable::URI::CharacterClasses::UNRESERVED
348: )
349: end
350: else
351: transformed_value = self.encode_component(
352: Addressable::IDNA.unicode_normalize_kc(transformed_value),
353: Addressable::URI::CharacterClasses::UNRESERVED
354: )
355: end
356:
357: # Process, if we've got a processor
358: if processor != nil
359: if processor.respond_to?(:validate)
360: if !processor.validate(name, value)
361: display_value = value.kind_of?(Array) ? value.inspect : value
362: raise InvalidTemplateValueError,
363: "#{name}=#{display_value} is an invalid template value."
364: end
365: end
366: if processor.respond_to?(:transform)
367: transformed_value = processor.transform(name, value)
368: end
369: end
370:
371: accu[name] = transformed_value
372: accu
373: end
374: result.gsub!(
375: /#{operator_expansion}|#{variable_expansion}/
376: ) do |capture|
377: if capture =~ operator_expansion
378: operator, argument, variables, default_mapping =
379: parse_template_expansion(capture, transformed_mapping)
380: expand_method = "expand_#{operator}_operator"
381: if ([expand_method, expand_method.to_sym] & private_methods).empty?
382: raise InvalidTemplateOperatorError,
383: "Invalid template operator: #{operator}"
384: else
385: send(expand_method.to_sym, argument, variables, default_mapping)
386: end
387: else
388: varname, _, vardefault = capture.scan(/^\{(.+?)(=(.*))?\}$/)[0]
389: transformed_mapping[varname] || vardefault
390: end
391: end
392: return Addressable::URI.parse(result)
393: end
Extracts uris from an arbitrary body of text.
@param [String, to_str] text
The body of text to extract URIs from.
@option [String, Addressable::URI, to_str] base
Causes any relative URIs to be resolved against the base URI.
@option [TrueClass, FalseClass] parse
If parse is true, all extracted URIs will be parsed. If parse is false, the return value with be an <tt>Array</tt> of <tt>Strings</aa>. Defaults to false.
@return [Array] The extracted URIs.
# File lib/addressable/uri.rb, line 1136
1136: def self.extract(text, options={})
1137: defaults = {:base => nil, :parse => false}
1138: options = defaults.merge(options)
1139: raise InvalidOptionError unless (options.keys - defaults.keys).empty?
1140: # This regular expression needs to be less forgiving or else it would
1141: # match virtually all text. Which isn't exactly what we're going for.
1142: extract_regex = /((([a-z\+]+):)[^ \n\<\>\"\\]+[\w\/])/
1143: extracted_uris =
1144: text.scan(extract_regex).collect { |match| match[0] }
1145: sgml_extract_regex = /<[^>]+href=\"([^\"]+?)\"[^>]*>/
1146: sgml_extracted_uris =
1147: text.scan(sgml_extract_regex).collect { |match| match[0] }
1148: extracted_uris.concat(sgml_extracted_uris - extracted_uris)
1149: textile_extract_regex = /\".+?\":([^ ]+\/[^ ]+)[ \,\.\;\:\?\!\<\>\"]/i
1150: textile_extracted_uris =
1151: text.scan(textile_extract_regex).collect { |match| match[0] }
1152: extracted_uris.concat(textile_extracted_uris - extracted_uris)
1153: parsed_uris = []
1154: base_uri = nil
1155: if options[:base] != nil
1156: base_uri = options[:base] if options[:base].kind_of?(self)
1157: base_uri = self.parse(options[:base].to_s) if base_uri == nil
1158: end
1159: for uri_string in extracted_uris
1160: begin
1161: if base_uri == nil
1162: parsed_uris << self.parse(uri_string)
1163: else
1164: parsed_uris << (base_uri + self.parse(uri_string))
1165: end
1166: rescue Exception
1167: nil
1168: end
1169: end
1170: parsed_uris = parsed_uris.select do |uri|
1171: (self.ip_based_schemes | [
1172: "file", "git", "svn", "mailto", "tel"
1173: ]).include?(uri.normalized_scheme)
1174: end
1175: if options[:parse]
1176: return parsed_uris
1177: else
1178: return parsed_uris.collect { |uri| uri.to_s }
1179: end
1180: end
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.
@param [String, Addressable::URI, to_str] uri
The URI string to parse. No parsing is performed if the object is already an <tt>Addressable::URI</tt>.
@param [Hash] hints
A <tt>Hash</tt> of hints to the heuristic parser. Defaults to
<tt>{:scheme => "http"}</tt>.
@return [Addressable::URI] The parsed URI.
# File lib/addressable/uri.rb, line 162
162: def self.heuristic_parse(uri, hints={})
163: # If we were given nil, return nil.
164: return nil unless uri
165: # If a URI object is passed, just return itself.
166: return uri if uri.kind_of?(self)
167: if !uri.respond_to?(:to_str)
168: raise TypeError, "Can't convert #{uri.class} into String."
169: end
170: # Otherwise, convert to a String
171: uri = uri.to_str.dup
172: hints = {
173: :scheme => "http"
174: }.merge(hints)
175: case uri
176: when /^http:\/+/
177: uri.gsub!(/^http:\/+/, "http://")
178: when /^feed:\/+http:\/+/
179: uri.gsub!(/^feed:\/+http:\/+/, "feed:http://")
180: when /^feed:\/+/
181: uri.gsub!(/^feed:\/+/, "feed://")
182: when /^file:\/+/
183: uri.gsub!(/^file:\/+/, "file:///")
184: end
185: parsed = self.parse(uri)
186: if parsed.scheme =~ /^[^\/?#\.]+\.[^\/?#]+$/
187: parsed = self.parse(hints[:scheme] + "://" + uri)
188: end
189: if parsed.authority == nil
190: if parsed.path =~ /^[^\/]+\./
191: new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1]
192: if new_host
193: new_path = parsed.path.gsub(
194: Regexp.new("^" + Regexp.escape(new_host)), "")
195: parsed.host = new_host
196: parsed.path = new_path
197: parsed.scheme = hints[:scheme]
198: end
199: end
200: end
201: return parsed
202: end
Joins several URIs together.
@param [String, Addressable::URI, to_str] *uris
The URIs to join.
@return [Addressable::URI] The joined URI.
@example
base = "http://example.com/"
uri = Addressable::URI.parse("relative/path")
Addressable::URI.join(base, uri)
#=> #<Addressable::URI:0xcab390 URI:http://example.com/relative/path>
# File lib/addressable/uri.rb, line 903
903: def self.join(*uris)
904: uri_objects = uris.collect do |uri|
905: if !uri.respond_to?(:to_str)
906: raise TypeError, "Can't convert #{uri.class} into String."
907: end
908: uri.kind_of?(self) ? uri : self.parse(uri.to_str)
909: end
910: result = uri_objects.shift.dup
911: for uri in uri_objects
912: result.join!(uri)
913: end
914: return result
915: end
Creates a new uri object from component parts.
@option [String, to_str] scheme The scheme component. @option [String, to_str] user The user component. @option [String, to_str] password The password component. @option [String, to_str] userinfo
The userinfo component. If this is supplied, the user and password components must be omitted.
@option [String, to_str] host The host component. @option [String, to_str] port The port component. @option [String, to_str] authority
The authority component. If this is supplied, the user, password, userinfo, host, and port components must be omitted.
@option [String, to_str] path The path component. @option [String, to_str] query The query component. @option [String, to_str] fragment The fragment component.
@return [Addressable::URI] The constructed URI object.
# File lib/addressable/uri.rb, line 1201
1201: def initialize(options={})
1202: if options.has_key?(:authority)
1203: if (options.keys & [:userinfo, :user, :password, :host, :port]).any?
1204: raise ArgumentError,
1205: "Cannot specify both an authority and any of the components " +
1206: "within the authority."
1207: end
1208: end
1209: if options.has_key?(:userinfo)
1210: if (options.keys & [:user, :password]).any?
1211: raise ArgumentError,
1212: "Cannot specify both a userinfo and either the user or password."
1213: end
1214: end
1215:
1216: self.validation_deferred = true
1217: self.scheme = options[:scheme] if options[:scheme]
1218: self.user = options[:user] if options[:user]
1219: self.password = options[:password] if options[:password]
1220: self.userinfo = options[:userinfo] if options[:userinfo]
1221: self.host = options[:host] if options[:host]
1222: self.port = options[:port] if options[:port]
1223: self.authority = options[:authority] if options[:authority]
1224: self.path = options[:path] if options[:path]
1225: self.query = options[:query] if options[:query]
1226: self.fragment = options[:fragment] if options[:fragment]
1227: self.validation_deferred = false
1228: end
Normalizes the encoding of a URI. Characters within a hostname are not percent encoded to allow for internationalized domain names.
@param [String, Addressable::URI, to_str] uri
The URI to encode.
@param [Class] returning
The type of object to return. This value may only be set to <tt>String</tt> or <tt>Addressable::URI</tt>. All other values are invalid. Defaults to <tt>String</tt>.
@return [String, Addressable::URI]
The encoded URI. The return type is determined by the <tt>returning</tt> parameter.
# File lib/addressable/uri.rb, line 1074
1074: def self.normalized_encode(uri, returning=String)
1075: if !uri.respond_to?(:to_str)
1076: raise TypeError, "Can't convert #{uri.class} into String."
1077: end
1078: if ![String, ::Addressable::URI].include?(returning)
1079: raise TypeError,
1080: "Expected String or Addressable::URI, got #{returning.inspect}"
1081: end
1082: uri_object = uri.kind_of?(self) ? uri : self.parse(uri.to_str)
1083: components = {
1084: :scheme => self.unencode_component(uri_object.scheme),
1085: :user => self.unencode_component(uri_object.user),
1086: :password => self.unencode_component(uri_object.password),
1087: :host => self.unencode_component(uri_object.host),
1088: :port => uri_object.port,
1089: :path => self.unencode_component(uri_object.path),
1090: :query => self.unencode_component(uri_object.query),
1091: :fragment => self.unencode_component(uri_object.fragment)
1092: }
1093: components.each do |key, value|
1094: if value != nil
1095: components[key] = Addressable::IDNA.unicode_normalize_kc(value.to_s)
1096: end
1097: end
1098: encoded_uri = Addressable::URI.new(
1099: :scheme => self.encode_component(components[:scheme],
1100: Addressable::URI::CharacterClasses::SCHEME),
1101: :user => self.encode_component(components[:user],
1102: Addressable::URI::CharacterClasses::AUTHORITY),
1103: :password => self.encode_component(components[:password],
1104: Addressable::URI::CharacterClasses::AUTHORITY),
1105: :host => components[:host],
1106: :port => components[:port],
1107: :path => self.encode_component(components[:path],
1108: Addressable::URI::CharacterClasses::PATH),
1109: :query => self.encode_component(components[:query],
1110: Addressable::URI::CharacterClasses::QUERY),
1111: :fragment => self.encode_component(components[:fragment],
1112: Addressable::URI::CharacterClasses::FRAGMENT)
1113: )
1114: if returning == String
1115: return encoded_uri.to_s
1116: elsif returning == ::Addressable::URI
1117: return encoded_uri
1118: end
1119: end
Returns a URI object based on the parsed string.
@param [String, Addressable::URI, to_str] uri
The URI string to parse. No parsing is performed if the object is already an <tt>Addressable::URI</tt>.
@return [Addressable::URI] The parsed URI.
# File lib/addressable/uri.rb, line 88
88: def self.parse(uri)
89: # If we were given nil, return nil.
90: return nil unless uri
91: # If a URI object is passed, just return itself.
92: return uri if uri.kind_of?(self)
93: if !uri.respond_to?(:to_str)
94: raise TypeError, "Can't convert #{uri.class} into String."
95: end
96: # Otherwise, convert to a String
97: uri = uri.to_str
98:
99: # If a URI object of the Ruby standard library variety is passed,
100: # convert it to a string, then parse the string.
101: # We do the check this way because we don't want to accidentally
102: # cause a missing constant exception to be thrown.
103: if uri.class.name =~ /^URI\b/
104: uri = uri.to_s
105: end
106:
107: # This Regexp supplied as an example in RFC 3986, and it works great.
108: uri_regex =
109: /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/
110: scan = uri.scan(uri_regex)
111: fragments = scan[0]
112: return nil if fragments.nil?
113: scheme = fragments[1]
114: authority = fragments[3]
115: path = fragments[4]
116: query = fragments[6]
117: fragment = fragments[8]
118: userinfo = nil
119: user = nil
120: password = nil
121: host = nil
122: port = nil
123: if authority != nil
124: # The Regexp above doesn't split apart the authority.
125: userinfo = authority[/^([^\[\]]*)@/, 1]
126: if userinfo != nil
127: user = userinfo.strip[/^([^:]*):?/, 1]
128: password = userinfo.strip[/:(.*)$/, 1]
129: end
130: host = authority.gsub(/^([^\[\]]*)@/, "").gsub(/:([^:@\[\]]*?)$/, "")
131: port = authority[/:([^:@\[\]]*?)$/, 1]
132: end
133: if port == ""
134: port = nil
135: end
136:
137: return Addressable::URI.new(
138: :scheme => scheme,
139: :user => user,
140: :password => password,
141: :host => host,
142: :port => port,
143: :path => path,
144: :query => query,
145: :fragment => fragment
146: )
147: end
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.
# File lib/addressable/uri.rb, line 1564
1564: def self.port_mapping
1565: @port_mapping ||= {
1566: "http" => 80,
1567: "https" => 443,
1568: "ftp" => 21,
1569: "tftp" => 69,
1570: "sftp" => 22,
1571: "ssh" => 22,
1572: "svn+ssh" => 22,
1573: "telnet" => 23,
1574: "nntp" => 119,
1575: "gopher" => 70,
1576: "wais" => 210,
1577: "ldap" => 389,
1578: "prospero" => 1525
1579: }
1580: end
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.
@param [String, Addressable::URI, to_str] uri
The URI or component to unencode.
@param [Class] returning
The type of object to return. This value may only be set to <tt>String</tt> or <tt>Addressable::URI</tt>. All other values are invalid. Defaults to <tt>String</tt>.
@return [String, Addressable::URI]
The unencoded component or URI. The return type is determined by the <tt>returning</tt> parameter.
# File lib/addressable/uri.rb, line 986
986: def self.unencode(uri, returning=String)
987: return nil if uri.nil?
988: if !uri.respond_to?(:to_str)
989: raise TypeError, "Can't convert #{uri.class} into String."
990: end
991: if ![String, ::Addressable::URI].include?(returning)
992: raise TypeError,
993: "Expected String or Addressable::URI, got #{returning.inspect}"
994: end
995: result = uri.to_str.gsub(/%[0-9a-f]{2}/i) do |sequence|
996: sequence[1..3].to_i(16).chr
997: end
998: result.force_encoding("utf-8") if result.respond_to?(:force_encoding)
999: if returning == String
1000: return result
1001: elsif returning == ::Addressable::URI
1002: return ::Addressable::URI.parse(result)
1003: end
1004: end
Returns true if the URI objects are equal. This method normalizes both URIs before doing the comparison.
@param [Object] uri The URI to compare.
@return [TrueClass, FalseClass]
<tt>true</tt> if the URIs are equivalent, <tt>false</tt> otherwise.
# File lib/addressable/uri.rb, line 2240
2240: def ==(uri)
2241: return false unless uri.kind_of?(self.class)
2242: return self.normalize.to_s == uri.normalize.to_s
2243: end
Returns true if the URI objects are equal. This method normalizes both URIs before doing the comparison, and allows comparison against Strings.
@param [Object] uri The URI to compare.
@return [TrueClass, FalseClass]
<tt>true</tt> if the URIs are equivalent, <tt>false</tt> otherwise.
# File lib/addressable/uri.rb, line 2219
2219: def ===(uri)
2220: if uri.respond_to?(:normalize)
2221: uri_string = uri.normalize.to_s
2222: else
2223: begin
2224: uri_string = ::Addressable::URI.parse(uri).normalize.to_s
2225: rescue InvalidURIError, TypeError
2226: return false
2227: end
2228: end
2229: return self.normalize.to_s == uri_string
2230: end
The authority component for this URI. Combines the user, password, host, and port components.
@return [String] The authority component.
# File lib/addressable/uri.rb, line 1481
1481: def authority
1482: @authority ||= (begin
1483: if self.host.nil?
1484: nil
1485: else
1486: authority = ""
1487: if self.userinfo != nil
1488: authority << "#{self.userinfo}@"
1489: end
1490: authority << self.host
1491: if self.port != nil
1492: authority << ":#{self.port}"
1493: end
1494: authority
1495: end
1496: end)
1497: end
Sets the authority component for this URI.
@param [String, to_str] new_authority The new authority component.
# File lib/addressable/uri.rb, line 1525
1525: def authority=(new_authority)
1526: if new_authority
1527: new_authority = new_authority.to_str
1528: new_userinfo = new_authority[/^([^\[\]]*)@/, 1]
1529: if new_userinfo
1530: new_user = new_userinfo.strip[/^([^:]*):?/, 1]
1531: new_password = new_userinfo.strip[/:(.*)$/, 1]
1532: end
1533: new_host =
1534: new_authority.gsub(/^([^\[\]]*)@/, "").gsub(/:([^:@\[\]]*?)$/, "")
1535: new_port =
1536: new_authority[/:([^:@\[\]]*?)$/, 1]
1537: end
1538:
1539: # Password assigned first to ensure validity in case of nil
1540: self.password = new_password
1541: self.user = new_user
1542: self.host = new_host
1543: self.port = new_port
1544:
1545: # Reset dependant values
1546: @inferred_port = nil
1547: @userinfo = nil
1548: @normalized_userinfo = nil
1549:
1550: # Ensure we haven't created an invalid URI
1551: validate()
1552: end
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.
@return [Addressable::URI] A URI suitable for display purposes.
# File lib/addressable/uri.rb, line 2203
2203: def display_uri
2204: display_uri = self.normalize
2205: display_uri.instance_variable_set("@host",
2206: ::Addressable::IDNA.to_unicode(display_uri.host))
2207: return display_uri
2208: end
Clones the URI object.
@return [Addressable::URI] The cloned URI.
# File lib/addressable/uri.rb, line 2271
2271: def dup
2272: duplicated_uri = Addressable::URI.new(
2273: :scheme => self.scheme ? self.scheme.dup : nil,
2274: :user => self.user ? self.user.dup : nil,
2275: :password => self.password ? self.password.dup : nil,
2276: :host => self.host ? self.host.dup : nil,
2277: :port => self.port,
2278: :path => self.path ? self.path.dup : nil,
2279: :query => self.query ? self.query.dup : nil,
2280: :fragment => self.fragment ? self.fragment.dup : nil
2281: )
2282: return duplicated_uri
2283: end
Returns true if the URI objects are equal. This method does NOT normalize either URI before doing the comparison.
@param [Object] uri The URI to compare.
@return [TrueClass, FalseClass]
<tt>true</tt> if the URIs are equivalent, <tt>false</tt> otherwise.
# File lib/addressable/uri.rb, line 2253
2253: def eql?(uri)
2254: return false unless uri.kind_of?(self.class)
2255: return self.to_s == uri.to_s
2256: end
Extracts a mapping from the URI using a URI Template pattern.
@param [String] pattern
A URI template pattern.
@param [restore, match] processor
A template processor object may optionally be supplied. The object should respond to either the <tt>restore</tt> or <tt>match</tt> messages or both. The <tt>restore</tt> method should take two parameters: [String] name and [String] value. The <tt>restore</tt> method should reverse any transformations that have been performed on the value to ensure a valid URI. The <tt>match</tt> method should take a single parameter: [String] name. The <tt>match</tt> method should return a <tt>String</tt> containing a regular expression capture group for matching on that particular variable. The default value is ".*?". The <tt>match</tt> method has no effect on multivariate operator expansions.
@return [Hash, NilClass]
The <tt>Hash</tt> mapping that was extracted from the URI, or <tt>nil</tt> if the URI didn't match the template.
@example
class ExampleProcessor
def self.restore(name, value)
return value.gsub(/\+/, " ") if name == "query"
return value
end
def self.match(name)
return ".*?" if name == "first"
return ".*"
end
end
uri = Addressable::URI.parse(
"http://example.com/search/an+example+search+query/"
)
uri.extract_mapping(
"http://example.com/search/{query}/",
ExampleProcessor
)
#=> {"query" => "an example search query"}
uri = Addressable::URI.parse("http://example.com/a/b/c/")
uri.extract_mapping(
"http://example.com/{first}/{second}/",
ExampleProcessor
)
#=> {"first" => "a", "second" => "b/c"}
uri = Addressable::URI.parse("http://example.com/a/b/c/")
uri.extract_mapping(
"http://example.com/{first}/{-list|/|second}/"
)
#=> {"first" => "a", "second" => ["b", "c"]}