Class: DiasporaFederation::Discovery::XrdDocument

Inherits:
Object
  • Object
show all
Defined in:
lib/diaspora_federation/discovery/xrd_document.rb

Overview

Note:

RFC 6415 recommends that servers should also offer the JRD format in addition to the XRD representation. Implementing XrdDocument#to_json and XrdDocument.json_data should be almost trivial due to the simplicity of the format and the way the data is stored internally already. See RFC 6415, Appendix A for a description of the JSON format.

This class implements basic handling of XRD documents as far as it is necessary in the context of the protocols used with diaspora* federation.

Examples:

Creating a XrdDocument

doc = XrdDocument.new
doc.expires = DateTime.new(2020, 1, 15, 0, 0, 1)
doc.subject = "http://example.tld/articles/11"
doc.aliases << "http://example.tld/cool_article"
doc.aliases << "http://example.tld/authors/2/articles/3"
doc.properties["http://x.example.tld/ns/version"] = "1.3"
doc.links << { rel: "author", type: "text/html", href: "http://example.tld/authors/2" }
doc.links << { rel: "copyright", template: "http://example.tld/copyright?id={uri}" }

doc.to_xml

Parsing a XrdDocument

data = XrdDocument.xml_data(xml_string)

See Also:

Constant Summary collapse

XMLNS =

xml namespace url

"http://docs.oasis-open.org/ns/xri/xrd-1.0".freeze
%i[rel type href template].freeze
DATETIME_FORMAT =

format string for datetime (Expires element)

"%Y-%m-%dT%H:%M:%SZ".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeXrdDocument

Returns a new instance of XrdDocument.



61
62
63
64
65
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 61

def initialize
  @aliases = []
  @links = []
  @properties = {}
end

Instance Attribute Details

#aliasesArray<String> (readonly)

Returns list of alias URIs.

Returns:

  • (Array<String>)

    list of alias URIs



50
51
52
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 50

def aliases
  @aliases
end

#expires=(value) ⇒ Object

The <Expires> element contains a time value which specifies the instant at and after which the document has expired and SHOULD NOT be used.

Parameters:

  • value (DateTime)


43
44
45
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 43

def expires=(value)
  @expires = value
end

Returns list of Link element hashes. Each hash contains the attributesa and their associated values for the Link element.

Returns:

  • (Array<Hash<attr => val>>)

    list of Link element hashes. Each hash contains the attributesa and their associated values for the Link element.



59
60
61
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 59

def links
  @links
end

#propertiesHash<String => mixed> (readonly)

Returns list of properties. Hash key represents the type attribute, and the value is the element content.

Returns:

  • (Hash<String => mixed>)

    list of properties. Hash key represents the type attribute, and the value is the element content



54
55
56
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 54

def properties
  @properties
end

#subject=(value) ⇒ Object

The <Subject> element contains a URI value which identifies the resource described by this XRD.

Parameters:

  • value (String)


47
48
49
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 47

def subject=(value)
  @subject = value
end

Class Method Details

.json_data(jrd_doc) ⇒ Hash

Parse the JRD document from the given string and create a hash containing the extracted data with symbolized keys.

Parameters:

  • jrd_doc (String)

    JSON string

Returns:

  • (Hash)

    extracted data

Raises:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 124

def self.json_data(jrd_doc)
  json_hash = JSON.parse(jrd_doc)

  {
    subject:    json_hash["subject"],
    expires:    (DateTime.strptime(json_hash["expires"], DATETIME_FORMAT) if json_hash.key?("expires")),
    aliases:    json_hash["aliases"],
    properties: json_hash["properties"],
    links:      symbolize_keys_for_links(json_hash["links"])
  }.reject {|_, v| v.nil? }
rescue JSON::JSONError => e
  raise InvalidDocument,
        "Not a JRD document: #{e.class}: #{e.message[0..255].encode(Encoding.default_external, undef: :replace)}"
end

.xml_data(xrd_doc) ⇒ Hash

Parse the XRD document from the given string and create a hash containing the extracted data.

Small bonus: the hash structure that comes out of this method is the same as the one used to produce a JRD (JSON Resource Descriptor) or parsing it.

Parameters:

  • xrd_doc (String)

    XML string

Returns:

  • (Hash)

    extracted data

Raises:



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 102

def self.xml_data(xrd_doc)
  doc = parse_xrd_document(xrd_doc)

  {}.tap do |data|
    exp_elem = doc.at_xpath("xrd:XRD/xrd:Expires", NS)
    data[:expires] = DateTime.strptime(exp_elem.content, DATETIME_FORMAT) unless exp_elem.nil?

    subj_elem = doc.at_xpath("xrd:XRD/xrd:Subject", NS)
    data[:subject] = subj_elem.content unless subj_elem.nil?

    parse_aliases_from_xml_doc(doc, data)
    parse_properties_from_xml_doc(doc, data)
    parse_links_from_xml_doc(doc, data)
  end
end

Instance Method Details

#to_jsonObject



83
84
85
86
87
88
89
90
91
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 83

def to_json
  {
    subject:    subject,
    expires:    (expires.strftime(DATETIME_FORMAT) if expires.instance_of?(DateTime)),
    aliases:    (aliases if aliases.any?),
    properties: (properties if properties.any?),
    links:      (links if links.any?)
  }.reject {|_, v| v.nil? }
end

#to_xmlString

Generates an XML document from the current instance and returns it as string

Returns:

  • (String)

    XML document



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/diaspora_federation/discovery/xrd_document.rb', line 69

def to_xml
  Nokogiri::XML::Builder.new(encoding: "UTF-8") {|xml|
    xml.XRD("xmlns" => XMLNS) {
      xml.Expires(expires.strftime(DATETIME_FORMAT)) if expires.instance_of?(DateTime)

      xml.Subject(subject) if !subject.nil? && !subject.empty?

      add_aliases_to(xml)
      add_properties_to(xml)
      add_links_to(xml)
    }
  }.to_xml
end