link_header 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +1 -1
- data/README.rdoc +15 -0
- data/lib/link_header.rb +88 -13
- data/test/test_link_header.rb +5 -0
- metadata +2 -2
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -9,6 +9,21 @@ Converts conforming link headers to and from text, LinkHeader objects and corres
|
|
9
9
|
== Installation
|
10
10
|
|
11
11
|
sudo gem install link_header
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
require "link_header"
|
16
|
+
|
17
|
+
LinkHeader.parse('<http://example.com/foo>; rel="self", <http://example.com/>; rel = "up"').to_a
|
18
|
+
#=> [["http://example.com/foo", [["rel", "self"]]],
|
19
|
+
["http://example.com/", [["rel", "up"]]]]
|
20
|
+
|
21
|
+
LinkHeader.new([
|
22
|
+
["http://example.com/foo", [["rel", "self"]]],
|
23
|
+
["http://example.com/", [["rel", "up"]]]]).to_s
|
24
|
+
#=> '<http://example.com/foo>; rel="self", <http://example.com/>; rel = "up"'
|
25
|
+
|
26
|
+
For more information see the LinkHeader and LinkHeader::Link classes (both defined in lib/link_header.rb).
|
12
27
|
|
13
28
|
== Author
|
14
29
|
|
data/lib/link_header.rb
CHANGED
@@ -1,21 +1,48 @@
|
|
1
1
|
require "strscan"
|
2
2
|
|
3
|
+
#
|
4
|
+
# Represents an HTTP link header of the form described in the draft spec http://tools.ietf.org/id/draft-nottingham-http-link-header-06.txt.
|
5
|
+
# It is simply a list of LinkHeader::Link objects and some conversion functions.
|
6
|
+
#
|
3
7
|
class LinkHeader
|
4
|
-
|
8
|
+
# rubygem version
|
9
|
+
VERSION = "0.0.4"
|
5
10
|
|
6
|
-
#
|
11
|
+
# An array of Link objects
|
7
12
|
attr_reader :links
|
8
13
|
|
9
14
|
#
|
10
|
-
# Initialize from
|
15
|
+
# Initialize from a collection of either LinkHeader::Link objects or data from which Link objects can be created.
|
16
|
+
#
|
17
|
+
# From a list of LinkHeader::Link objects:
|
18
|
+
#
|
19
|
+
# LinkHeader.new([
|
20
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"]]),
|
21
|
+
# LinkHeader::Link.new("http://example.com/", [["rel", "up"]])])
|
22
|
+
#
|
23
|
+
# From the equivalent JSON-friendly raw data:
|
24
|
+
#
|
25
|
+
# LinkHeader.new([
|
26
|
+
# ["http://example.com/foo", [["rel", "self"]]],
|
27
|
+
# ["http://example.com/", [["rel", "up"]]]]).to_s
|
28
|
+
#
|
29
|
+
# See also LinkHeader.parse
|
11
30
|
#
|
12
31
|
def initialize(links=[])
|
13
|
-
|
32
|
+
if links
|
33
|
+
@links = links.map{|l| l.kind_of?(Link) ? l : Link.new(*l)}
|
34
|
+
else
|
35
|
+
@links = []
|
36
|
+
end
|
14
37
|
end
|
15
38
|
|
16
39
|
#
|
17
40
|
# Convert to a JSON-friendly array
|
18
41
|
#
|
42
|
+
# LinkHeader.parse('<http://example.com/foo>; rel="self", <http://example.com/>; rel = "up"').to_a
|
43
|
+
# #=> [["http://example.com/foo", [["rel", "self"]]],
|
44
|
+
# ["http://example.com/", [["rel", "up"]]]]
|
45
|
+
#
|
19
46
|
def to_a
|
20
47
|
links.map{|l| l.to_a}
|
21
48
|
end
|
@@ -23,6 +50,11 @@ class LinkHeader
|
|
23
50
|
#
|
24
51
|
# Convert to string representation as per the link header spec
|
25
52
|
#
|
53
|
+
# LinkHeader.new([
|
54
|
+
# ["http://example.com/foo", [["rel", "self"]]],
|
55
|
+
# ["http://example.com/", [["rel", "up"]]]]).to_s
|
56
|
+
# #=> '<http://example.com/foo>; rel="self", <http://example.com/>; rel = "up"'
|
57
|
+
#
|
26
58
|
def to_s
|
27
59
|
links.join(', ')
|
28
60
|
end
|
@@ -33,16 +65,20 @@ class LinkHeader
|
|
33
65
|
# Acknowledgement: The QUOTED regexp is based on
|
34
66
|
# http://stackoverflow.com/questions/249791/regexp-for-quoted-string-with-escaping-quotes/249937#249937
|
35
67
|
#
|
36
|
-
HREF = / *< *([^>]*) *> *;? */
|
37
|
-
TOKEN = /([^()<>@,;:\"\[\]?={}\s]+)/
|
38
|
-
QUOTED = /"((?:[^"\\]|\\.)*)"/
|
39
|
-
ATTR = /#{TOKEN} *= *(#{TOKEN}|#{QUOTED}) */
|
40
|
-
SEMI = /; */
|
41
|
-
COMMA = /, */
|
68
|
+
HREF = / *< *([^>]*) *> *;? */ #:nodoc: note: no attempt to check URI validity
|
69
|
+
TOKEN = /([^()<>@,;:\"\[\]?={}\s]+)/ #:nodoc: non-empty sequence of non-separator characters
|
70
|
+
QUOTED = /"((?:[^"\\]|\\.)*)"/ #:nodoc: double-quoted strings with backslash-escaped double quotes
|
71
|
+
ATTR = /#{TOKEN} *= *(#{TOKEN}|#{QUOTED}) */ #:nodoc:
|
72
|
+
SEMI = /; */ #:nodoc:
|
73
|
+
COMMA = /, */ #:nodoc:
|
42
74
|
|
43
75
|
#
|
44
76
|
# Parse a link header, returning a new LinkHeader object
|
45
77
|
#
|
78
|
+
# LinkHeader.parse('<http://example.com/foo>; rel="self", <http://example.com/>; rel = "up"').to_a
|
79
|
+
# #=> [["http://example.com/foo", [["rel", "self"]]],
|
80
|
+
# ["http://example.com/", [["rel", "up"]]]]
|
81
|
+
#
|
46
82
|
def self.parse(link_header)
|
47
83
|
return new unless link_header
|
48
84
|
|
@@ -62,20 +98,44 @@ class LinkHeader
|
|
62
98
|
|
63
99
|
new(links)
|
64
100
|
end
|
65
|
-
|
101
|
+
|
102
|
+
def find_link(*attr_pairs)
|
103
|
+
links.detect do |link|
|
104
|
+
!attr_pairs.detect do |pair|
|
105
|
+
!link.attr_pairs.include?(pair)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
66
110
|
#
|
67
111
|
# Represents a link - an href and a list of attributes (key value pairs)
|
68
112
|
#
|
113
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"]]).to_s
|
114
|
+
# => '<http://example.com/foo>; rel="self"'
|
115
|
+
#
|
69
116
|
class Link
|
70
|
-
#
|
117
|
+
#
|
118
|
+
# The link's URI string
|
119
|
+
#
|
120
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"]]).href
|
121
|
+
# => 'http://example.com/foo>'
|
122
|
+
#
|
71
123
|
attr_reader :href
|
72
124
|
|
125
|
+
#
|
73
126
|
# The link's attributes, an array of key-value pairs
|
127
|
+
#
|
128
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"], ["rel", "canonical"]]).attr_pairs
|
129
|
+
# => [["rel", "self"], ["rel", "canonical"]]
|
130
|
+
#
|
74
131
|
attr_reader :attr_pairs
|
75
132
|
|
76
133
|
#
|
77
134
|
# Initialize a Link from an href and attribute list
|
78
135
|
#
|
136
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"]]).to_s
|
137
|
+
# => '<http://example.com/foo>; rel="self"'
|
138
|
+
#
|
79
139
|
def initialize(href, attr_pairs)
|
80
140
|
@href, @attr_pairs = href, attr_pairs
|
81
141
|
end
|
@@ -83,12 +143,17 @@ class LinkHeader
|
|
83
143
|
#
|
84
144
|
# Lazily convert the attribute list to a Hash
|
85
145
|
#
|
146
|
+
# Beware repeated attribute names (it's safer to use #attr_pairs if this is risk):
|
147
|
+
#
|
148
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"], ["rel", "canonical"]]).attrs
|
149
|
+
# => {"rel" =>"canonical"}
|
150
|
+
#
|
86
151
|
def attrs
|
87
152
|
@attrs ||= Hash[*attr_pairs.flatten]
|
88
153
|
end
|
89
154
|
|
90
155
|
#
|
91
|
-
# Access
|
156
|
+
# Access #attrs by key
|
92
157
|
#
|
93
158
|
def [](key)
|
94
159
|
attrs[key]
|
@@ -97,13 +162,23 @@ class LinkHeader
|
|
97
162
|
#
|
98
163
|
# Convert to a JSON-friendly Array
|
99
164
|
#
|
165
|
+
# LinkHeader::Link.new("http://example.com/foo", [["rel", "self"], ["rel", "canonical"]]).to_a
|
166
|
+
# => ["http://example.com/foo", [["rel", "self"], ["rel", "canonical"]]]
|
167
|
+
#
|
100
168
|
def to_a
|
101
169
|
[href, attr_pairs]
|
102
170
|
end
|
103
171
|
|
172
|
+
#
|
173
|
+
# Convert to string representation as per the link header spec. This includes backspace-escaping doublequote characters in
|
174
|
+
# quoted attribute values.
|
175
|
+
#
|
104
176
|
#
|
105
177
|
# Convert to string representation as per the link header spec
|
106
178
|
#
|
179
|
+
# LinkHeader::Link.new(["http://example.com/foo", [["rel", "self"]]]).to_s
|
180
|
+
# #=> '<http://example.com/foo>; rel="self"'
|
181
|
+
#
|
107
182
|
def to_s
|
108
183
|
(["<#{href}>"] + attr_pairs.map{|k, v| "#{k}=\"#{v.gsub(/"/, '\"')}\""}).join('; ')
|
109
184
|
end
|
data/test/test_link_header.rb
CHANGED
@@ -61,4 +61,9 @@ class TestLinkHeader < Test::Unit::TestCase
|
|
61
61
|
def test_format_attribute
|
62
62
|
assert_equal('<any old stuff!>; a-token="escaped \""', LinkHeader.new([['any old stuff!', [['a-token', 'escaped "']]]]).to_s)
|
63
63
|
end
|
64
|
+
|
65
|
+
def test_find_link
|
66
|
+
link_header = LinkHeader.new(LINK_HEADER_A)
|
67
|
+
assert_equal([["rel", "self"]], link_header.find_link(["rel", "self"]).attr_pairs)
|
68
|
+
end
|
64
69
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: link_header
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Burrows
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-27 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|