httpclient_link_header 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,77 @@
1
+ require 'httpclient'
2
+
3
+ module HTTP
4
+ class LinkHeaders
5
+ PARAM_REG = /(\w+)=['"](\w+)['"]/
6
+ LINK_REG = /<(.+)>((?:; \w+=['"]\w+['"])*)/
7
+
8
+ def self.parse(link_headers)
9
+ unless link_headers.empty?
10
+ new(parse_link_headers(link_headers))
11
+ end
12
+ end
13
+
14
+ def self.generate(links)
15
+ links.map do |link|
16
+ params = (link['params'] || []).map { |key, value| "; #{key}=\"#{value}\"" }.join
17
+ "<#{link['uri']}>#{params}"
18
+ end
19
+ end
20
+
21
+ def initialize(parsed_headers)
22
+ @parsed_headers = parsed_headers
23
+ end
24
+
25
+ def by(param)
26
+ index_by(param, @parsed_headers)
27
+ end
28
+
29
+ private
30
+
31
+ def self.parse_link_header(link_header)
32
+ parsed = {}
33
+ match = LINK_REG.match(link_header)
34
+ uri, params = match.captures
35
+ parsed['uri'] = uri
36
+ params_split = params.split(";").reject(&:empty?).map(&:strip)
37
+ parsed['params'] = params_split.inject({}) do |pout, param|
38
+ param_match = PARAM_REG.match(param)
39
+ key, value = param_match.captures
40
+ pout[key] = value
41
+ pout
42
+ end
43
+ parsed
44
+ end
45
+
46
+ def self.parse_link_headers(link_headers)
47
+ link_headers.map { |lh| parse_link_header(lh) }
48
+ end
49
+
50
+ def index_by(param, parsed_headers)
51
+ parsed_headers.inject({}) do |index, header|
52
+ param_value = header['params'][param]
53
+ if param_value
54
+ unless index.has_key?(param_value)
55
+ index[param_value] = []
56
+ end
57
+ index[param_value] << header
58
+ end
59
+ index
60
+ end
61
+ end
62
+ end
63
+
64
+ module MLinkHeaders
65
+ LINK_HEADER = "Link"
66
+
67
+ def links
68
+ LinkHeaders.parse(header[LINK_HEADER])
69
+ end
70
+
71
+ def links=(links)
72
+ header.set(LINK_HEADER, LinkHeaders.generate(links))
73
+ end
74
+ end
75
+ end
76
+
77
+ HTTP::Message.send(:include, HTTP::MLinkHeaders)
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+ require 'httpclient_link_header'
3
+ require 'httpclient'
4
+
5
+ class TestLinkHeader < Test::Unit::TestCase
6
+ def test_link_header_parsing
7
+ expected = "compact.css"
8
+ resp = HTTP::Message.new_response(nil)
9
+ resp.header['Link'] = '<compact.css>; rel="stylesheet"; title="hello"'
10
+
11
+ assert_equal(expected, resp.links.by('rel').fetch('stylesheet').first['uri'])
12
+ assert_equal(expected, resp.links.by('title').fetch('hello').first['uri'])
13
+ end
14
+
15
+ def test_link_header_parsing_with_no_links
16
+ resp = HTTP::Message.new_response(nil)
17
+
18
+ assert_equal(nil, resp.links)
19
+ end
20
+
21
+ def test_link_header_generation
22
+ with_params = '<compact.css>; rel="stylesheet"; title="hello"'
23
+ without_params = '<compact.css>'
24
+
25
+ resp = HTTP::Message.new_request('GET', '/')
26
+ resp.links = [
27
+ {'uri' => 'compact.css', 'params' => {'rel' => 'stylesheet', 'title' => 'hello'}},
28
+ {'uri' => 'compact.css'}
29
+ ]
30
+ links = resp.header['Link']
31
+
32
+ assert_equal(2, links.size)
33
+ assert_equal(with_params, links[0])
34
+ assert_equal(without_params, links[1])
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: httpclient_link_header
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - TempoDB, Inc.
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-03-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httpclient
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Parse and process W3C compliant Link headers within HTTPClient (http://www.w3.org/Protocols/9707-link-header.html)
31
+ email: software@tempo-db.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/httpclient_link_header.rb
37
+ - test/test_httpclient_link_header.rb
38
+ homepage: http://tempo-db.com
39
+ licenses: []
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 1.8.25
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: HTTPClient Link Header Parser
62
+ test_files:
63
+ - test/test_httpclient_link_header.rb