Class: Furi::Uri

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

Instance Method Summary collapse

Constructor Details

#initialize(argument) ⇒ Uri

Returns a new instance of Uri.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/furi/uri.rb', line 18

def initialize(argument)
  @query_tokens = []
  case argument
  when String
    parse_uri_string(argument)
  when Hash
    replace(argument)
  when ::URI::Generic
    parse_uri_string(argument.to_s)
  else
    raise ParseError, "wrong Uri argument"
  end
end

Instance Method Details

#==(other) ⇒ Object



446
447
448
# File 'lib/furi/uri.rb', line 446

def ==(other)
  to_s == other.to_s
end

#[](part) ⇒ Object



459
460
461
# File 'lib/furi/uri.rb', line 459

def [](part)
  send(part)
end

#[]=(part, value) ⇒ Object



463
464
465
# File 'lib/furi/uri.rb', line 463

def []=(part, value)
  send(:"#{part}=", value)
end

#abstract_protocol?Boolean

Returns:

  • (Boolean)


417
418
419
# File 'lib/furi/uri.rb', line 417

def abstract_protocol?
  protocol == ""
end

#anchor=(string) ⇒ Object



454
455
456
457
# File 'lib/furi/uri.rb', line 454

def anchor=(string)
  string = string.to_s
  @anchor = string.empty? ? nil : string
end

#authorityObject



158
159
160
161
# File 'lib/furi/uri.rb', line 158

def authority
  return hostinfo unless userinfo
  [userinfo, hostinfo].join("@")
end

#authority=(string) ⇒ Object



163
164
165
166
167
168
169
170
171
# File 'lib/furi/uri.rb', line 163

def authority=(string)
  if string.include?("@")
    userinfo, string = string.split("@", 2)
    self.userinfo = userinfo
  else
    self.userinfo = nil
  end
  self.hostinfo = string
end

#custom_port?Boolean

Returns:

  • (Boolean)


486
487
488
# File 'lib/furi/uri.rb', line 486

def custom_port?
  port && port != default_port
end

#default_portObject



382
383
384
# File 'lib/furi/uri.rb', line 382

def default_port
  Furi::PROTOCOLS.fetch(protocol, {})[:port]
end

#default_web_port?Boolean

Returns:

  • (Boolean)


407
408
409
410
411
# File 'lib/furi/uri.rb', line 407

def default_web_port?
  Furi::WEB_PROTOCOL.any? do |web_protocol|
    Furi::PROTOCOLS[web_protocol][:port] == port!
  end
end

#defaults(parts) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/furi/uri.rb', line 54

def defaults(parts)
  parts.each do |part, value|
    case part.to_sym
    when :query, :query_tokens
      Furi.parse_query(value).each do |key, default_value|
        unless query.key?(key)
          query[key] = default_value
        end
      end
    else
      unless self[part]
        self[part] = value
      end
    end
  end
  self
end

#directoryObject



309
310
311
# File 'lib/furi/uri.rb', line 309

def directory
  path_tokens[0..-2].join("/")
end

#directory=(string) ⇒ Object



313
314
315
316
317
318
319
# File 'lib/furi/uri.rb', line 313

def directory=(string)
  string ||= "/"
  if file && string !~ %r{/\z}
    string += '/'
  end
  self.path = string + file.to_s
end

#domainObject



121
122
123
# File 'lib/furi/uri.rb', line 121

def domain
  join_domain(parsed_host[1..2].flatten)
end

#domain=(new_domain) ⇒ Object



125
126
127
# File 'lib/furi/uri.rb', line 125

def domain=(new_domain)
  self.host= [subdomain, new_domain]
end

#domainnameObject



113
114
115
# File 'lib/furi/uri.rb', line 113

def domainname
  parsed_host[1]
end

#domainname=(new_domainname) ⇒ Object



117
118
119
# File 'lib/furi/uri.rb', line 117

def domainname=(new_domainname)
  self.domain = join_domain([subdomain, new_domainname, domainzone])
end

#domainzoneObject



105
106
107
# File 'lib/furi/uri.rb', line 105

def domainzone
  parsed_host.last
end

#domainzone=(new_zone) ⇒ Object



109
110
111
# File 'lib/furi/uri.rb', line 109

def domainzone=(new_zone)
  self.host = [subdomain, domainname, new_zone]
end

#emailObject



482
483
484
# File 'lib/furi/uri.rb', line 482

def email
  authority
end

#email=(email) ⇒ Object



477
478
479
480
# File 'lib/furi/uri.rb', line 477

def email=(email)
  self.protocol ||= "mailto"
  self.authority = email
end

#extensionObject



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

def extension
  return nil unless file
  file_tokens.size > 1 ? file_tokens.last : nil
end

#extension=(string) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/furi/uri.rb', line 326

def extension=(string)
  tokens = file_tokens
  case tokens.size
  when 0
    raise Furi::FormattingError, "can not assign extension when there is no file"
  when 1
    tokens.push(string)
  else
    if string
      tokens[-1] = string
    else
      tokens.pop
    end
  end
  self.file = tokens.join(".")
end

#fileObject



398
399
400
401
# File 'lib/furi/uri.rb', line 398

def file
  result = path_tokens.last
  result == "" ? nil : result
end

#file!Object



403
404
405
# File 'lib/furi/uri.rb', line 403

def file!
  file || ''
end

#file=(name) ⇒ Object



343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/furi/uri.rb', line 343

def file=(name)
  unless name
    return unless path
  else
    name = name.gsub(%r{\A/}, "")
  end

  self.path = path_tokens.tap do |p|
    filename_index = [p.size-1, 0].max
    p[filename_index] = name
  end.join("/")
end

#home_page?Boolean

Returns:

  • (Boolean)


224
225
226
# File 'lib/furi/uri.rb', line 224

def home_page?
  path! == Furi::ROOT || path! == "/index.html"
end

#host!Object



442
443
444
# File 'lib/furi/uri.rb', line 442

def host!
  host || ""
end

#host=(host) ⇒ Object



94
95
96
97
98
99
100
101
102
103
# File 'lib/furi/uri.rb', line 94

def host=(host)
  @host = case host
          when Array
            join_domain(host)
          when "", nil
            nil
          else
            host.to_s.downcase
          end
end

#hostinfoObject



137
138
139
140
141
142
143
# File 'lib/furi/uri.rb', line 137

def hostinfo
  return host unless custom_port?
  if port && !host
    raise Furi::FormattingError, "can not build URI with port but without host"
  end
  [host, port].join(":")
end

#hostinfo=(string) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/furi/uri.rb', line 145

def hostinfo=(string)
  if string.match(%r{\A\[.+\]\z}) #ipv6 host
    self.host = string
  else
    if match = string.match(/\A(.+):(.*)\z/)
      self.host, self.port = match.captures
    else
      self.host = string
      self.port = nil
    end
  end
end

#inspectObject



450
451
452
# File 'lib/furi/uri.rb', line 450

def inspect
  "#<#{self.class} #{to_s.inspect}>"
end

#locationObject



186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/furi/uri.rb', line 186

def location
  if protocol
    if !host && !mailto?
      raise Furi::FormattingError, "can not build URI with protocol but without host"
    end
    [
      protocol.empty? ? "" : "#{protocol}:", authority
    ].join(mailto? ? "" : "//")
  else
    authority
  end
end

#location=(string) ⇒ Object



199
200
201
202
203
204
205
# File 'lib/furi/uri.rb', line 199

def location=(string)
  string ||= ""
  string  = string.gsub(%r(/\Z), '')
  self.protocol = nil
  string = parse_protocol(string)
  self.authority = string
end

#mailto?Boolean

Returns:

  • (Boolean)


490
491
492
# File 'lib/furi/uri.rb', line 490

def mailto?
  protocol == "mailto"
end

#merge_query(query) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/furi/uri.rb', line 72

def merge_query(query)
  case query
  when Hash
    self.query = self.query.merge(Furi::Utils.stringify_keys(query))
  when String, Array
    self.query_tokens += Furi.query_tokens(query)
  when nil
  else
    raise QueryParseError, "#{query.inspect} can not be merged"
  end
end

#password=(password) ⇒ Object



284
285
286
# File 'lib/furi/uri.rb', line 284

def password=(password)
  @password = password.nil? ? nil : password.to_s
end

#path!Object



434
435
436
# File 'lib/furi/uri.rb', line 434

def path!
  path || Furi::ROOT
end

#path=(path) ⇒ Object



294
295
296
297
298
299
# File 'lib/furi/uri.rb', line 294

def path=(path)
  @path = path.to_s
  if !@path.empty? && !@path.start_with?("/")
    @path = "/" + @path
  end
end

#path_tokensObject



356
357
358
359
# File 'lib/furi/uri.rb', line 356

def path_tokens
  return [] unless path
  path.split("/", -1)
end

#port!Object



378
379
380
# File 'lib/furi/uri.rb', line 378

def port!
  port || default_port
end

#port=(port) ⇒ Object



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/furi/uri.rb', line 251

def port=(port)
  @port = case port
          when String
            if port.empty?
              nil
            else
              unless port =~ /\A\s*\d+\s*\z/
                raise ArgumentError, "port should be an Integer >= 0"
              end
              port.to_i
            end
          when Integer
            if port < 0
              raise ArgumentError, "port should be an Integer >= 0"
            end
            port
          when nil
            nil
          else
            raise ArgumentError, "can not parse port: #{port.inspect}"
          end
  @port
end

#protocol!Object



305
306
307
# File 'lib/furi/uri.rb', line 305

def protocol!
  protocol || default_protocol_for_port || 'http' # Web Rules Them All!
end

#protocol=(protocol) ⇒ Object



301
302
303
# File 'lib/furi/uri.rb', line 301

def protocol=(protocol)
  @protocol = protocol ? protocol.gsub(%r{:?/?/?\Z}, "").downcase : nil
end

#queryObject



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

def query
  return @query if query_level?
  @query = Furi.parse_query(query_tokens)
end

#query=(value) ⇒ Object



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/furi/uri.rb', line 234

def query=(value)
  case value
  when true
    # Assuming that current query needs to be parsed to Hash
    query
  when String, Array
    self.query_tokens = value
    @query = nil
  when Hash
    self.query_tokens = value
    @query = value
  when nil
  else
    raise QueryParseError, 'Query can only be Hash or String'
  end
end

#query_stringObject



362
363
364
365
366
367
368
# File 'lib/furi/uri.rb', line 362

def query_string
  if query_level?
    Furi.serialize(query)
  else
    query_tokens.any? ? query_tokens.join("&") : nil
  end
end

#query_string!Object



370
371
372
# File 'lib/furi/uri.rb', line 370

def query_string!
  query_string || ""
end

#query_string=(string) ⇒ Object



374
375
376
# File 'lib/furi/uri.rb', line 374

def query_string=(string)
  self.query_tokens = string.to_s
end

#query_tokens=(tokens) ⇒ Object



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

def query_tokens=(tokens)
  @query = nil
  @query_tokens = Furi.query_tokens(tokens)
end

#replace(parts) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/furi/uri.rb', line 32

def replace(parts)
  if parts
    parts.each do |part, value|
      self[part] = value
    end
  end
  self
end

#requestObject



207
208
209
210
211
212
213
# File 'lib/furi/uri.rb', line 207

def request
  return nil if !path && query_tokens.empty?
  result = []
  result << path!
  result << "?" << query_string if query_tokens.any?
  result.join
end

#request!Object



215
216
217
# File 'lib/furi/uri.rb', line 215

def request!
  request || path!
end

#request=(string) ⇒ Object



219
220
221
222
# File 'lib/furi/uri.rb', line 219

def request=(string)
  string = parse_anchor_and_query(string)
  self.path = string
end

#resourceObject



421
422
423
424
# File 'lib/furi/uri.rb', line 421

def resource
  return nil unless request
  request + encoded_anchor
end

#resource!Object



438
439
440
# File 'lib/furi/uri.rb', line 438

def resource!
  resource || request!
end

#resource=(value) ⇒ Object



426
427
428
429
430
431
432
# File 'lib/furi/uri.rb', line 426

def resource=(value)
  self.anchor = nil
  self.query_tokens = []
  self.path = nil
  value = parse_anchor_and_query(value)
  self.path = value
end

#rfc3986?Boolean

Returns:

  • (Boolean)


471
472
473
474
475
# File 'lib/furi/uri.rb', line 471

def rfc3986?
  uri = to_s
  !!(uri.match(URI::RFC3986_Parser::RFC3986_URI) ||
     uri.match(URI::RFC3986_Parser::RFC3986_relative_ref))
end

#rfc?Boolean

Returns:

  • (Boolean)


467
468
469
# File 'lib/furi/uri.rb', line 467

def rfc?
  rfc3986?
end

#sslObject



390
391
392
# File 'lib/furi/uri.rb', line 390

def ssl
  ssl?
end

#ssl=(ssl) ⇒ Object



394
395
396
# File 'lib/furi/uri.rb', line 394

def ssl=(ssl)
  self.protocol = find_protocol_for_ssl(ssl)
end

#ssl?Boolean

Returns:

  • (Boolean)


386
387
388
# File 'lib/furi/uri.rb', line 386

def ssl?
  !!(Furi::PROTOCOLS.fetch(protocol, {})[:ssl])
end

#subdomainObject



129
130
131
# File 'lib/furi/uri.rb', line 129

def subdomain
  parsed_host.first
end

#subdomain=(new_subdomain) ⇒ Object



133
134
135
# File 'lib/furi/uri.rb', line 133

def subdomain=(new_subdomain)
  self.host = [new_subdomain, domain]
end

#to_sObject



173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/furi/uri.rb', line 173

def to_s
  result = []
  result << location
  result << (host || mailto? ? path : path!)
  if query_tokens.any?
    result << "?" << query_string
  end
  if anchor
    result << encoded_anchor
  end
  result.join
end

#update(parts) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/furi/uri.rb', line 41

def update(parts)
  return self unless parts
  parts.each do |part, value|
    case part.to_sym
    when :query, :query_tokens, :query_string
      merge_query(value)
    else
      self[part] = value
    end
  end
  self
end

#userinfoObject



84
85
86
87
88
89
90
91
92
# File 'lib/furi/uri.rb', line 84

def userinfo
  if username
    [username, password].compact.join(":")
  elsif password
    raise Furi::FormattingError, "can not build URI with password but without username"
  else
    nil
  end
end

#userinfo=(userinfo) ⇒ Object



288
289
290
291
292
# File 'lib/furi/uri.rb', line 288

def userinfo=(userinfo)
  username, password = (userinfo || "").split(":", 2)
  self.username = username
  self.password = password
end

#username=(username) ⇒ Object



280
281
282
# File 'lib/furi/uri.rb', line 280

def username=(username)
  @username = username.nil? ? nil : username.to_s
end

#web_protocol?Boolean

Returns:

  • (Boolean)


413
414
415
# File 'lib/furi/uri.rb', line 413

def web_protocol?
  Furi::WEB_PROTOCOL.include?(protocol)
end