Class: Ur::Weblink

Inherits:
Object
  • Object
show all
Defined in:
lib/ur/weblink.rb

Overview

Defined Under Namespace

Classes: Error, NoContextError, ParseError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target_uri, attributes, context_uri = nil) ⇒ Weblink

Returns a new instance of Weblink.



61
62
63
64
65
# File 'lib/ur/weblink.rb', line 61

def initialize(target_uri, attributes, context_uri=nil)
  @target_uri = to_addressable_uri(target_uri)
  @attributes = attributes
  @context_uri = to_addressable_uri(context_uri)
end

Instance Attribute Details

#attributesObject (readonly)

link attributes



93
94
95
# File 'lib/ur/weblink.rb', line 93

def attributes
  @attributes
end

#context_uriObject (readonly) Also known as: context_iri

the context uri of the link, as an Addressable URI. this URI must be absolute, and the target_uri may be resolved against it. this is most typically the request URI of a request to a service



69
70
71
# File 'lib/ur/weblink.rb', line 69

def context_uri
  @context_uri
end

#target_uriObject (readonly) Also known as: target_iri

returns the target URI as an Addressable::URI



75
76
77
# File 'lib/ur/weblink.rb', line 75

def target_uri
  @target_uri
end

Class Method Details

parses an array of Web Links from the value an HTTP Link header, as described in https://tools.ietf.org/html/rfc5988#section-5

returns an Array of Weblink objects



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/ur/weblink.rb', line 27

def self.parse_link_value(link_value, context_uri=nil)
  links = []

  return links unless link_value

  attr_char = /[a-zA-Z0-9!#\$&+\-.^_`|~]/ # defined in https://tools.ietf.org/html/rfc5987#section-3.2.1
  ptoken = %r([a-zA-Z0-9!#\$%&'()*+\-./:<=>?@\[\]^_`{|}~])
  quoted_string = /"([^"]*)"/

  ss = StringScanner.new(link_value)
  parse_fail = proc do
    raise ParseError, "Unable to parse link value: #{link_value} " +
      "around character #{ss.pos}: #{ss.peek(link_value.length - ss.pos)}"
  end

  while !ss.eos?
    # get the target_uri, within some angle brackets
    ss.scan(/\s*<([^>]+)>/) || parse_fail.call
    target_uri = ss[1]
    attributes = {}
    # get the attributes: semicolon, some attr_chars, an optional asterisk, equals, and a quoted
    # string or series of unquoted ptokens
    while ss.scan(/\s*;\s*(#{attr_char.source}+\*?)\s*=\s*(?:#{quoted_string.source}|(#{ptoken.source}+))\s*/)
      attributes[ss[1]] = ss[2] || ss[3]
    end
    links << new(target_uri, attributes, context_uri)
    unless ss.eos?
      # either the string ends or has a comma followed by another link
      ss.scan(/\s*,\s*/) || parse_fail.call
    end
  end
  links
end

Instance Method Details

#[](attribute_key) ⇒ Object

subscript returns an attribute of this Link, if defined, otherwise nil



96
97
98
# File 'lib/ur/weblink.rb', line 96

def [](attribute_key)
  @attributes[attribute_key]
end

#absolute_target_uriObject

attempts to make target_uri absolute, using context_uri if available. raises if there is not information available to make an absolute target URI



82
83
84
85
86
87
88
89
90
# File 'lib/ur/weblink.rb', line 82

def absolute_target_uri
  if target_uri.absolute?
    target_uri
  elsif context_uri
    context_uri + target_uri
  else
    raise NoContextError, "Target URI is relative but no Context URI given - cannot determine absolute target URI"
  end
end

#relObject Also known as: relation_type

link rel attribute



101
102
103
# File 'lib/ur/weblink.rb', line 101

def rel
  self['rel']
end

#rel?(other_rel) ⇒ Boolean

compares relation types in a case-insensitive manner as mandated in https://tools.ietf.org/html/rfc5988#section-4.1

Returns:

  • (Boolean)


109
110
111
# File 'lib/ur/weblink.rb', line 109

def rel?(other_rel)
  rel && other_rel && rel.downcase == other_rel.downcase
end

#to_sObject

a string of this weblink, appropriate for adding to a Link header



114
115
116
# File 'lib/ur/weblink.rb', line 114

def to_s
  "<#{target_uri}>" + attributes.map { |k,v| %Q(; #{k}="#{v}") }.join('')
end