link-header-parser 0.2.0 → 2.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -1
- data/CONTRIBUTING.md +3 -3
- data/README.md +54 -36
- data/lib/link-header-parser.rb +11 -7
- data/lib/link_header_parser/link_header.rb +106 -0
- data/lib/link_header_parser/link_header_parameter.rb +41 -0
- data/lib/link_header_parser/link_headers_collection.rb +48 -0
- data/lib/link_header_parser/version.rb +1 -1
- data/link-header-parser.gemspec +8 -20
- metadata +14 -136
- data/.editorconfig +0 -14
- data/.gitignore +0 -34
- data/.reek.yml +0 -9
- data/.rspec +0 -2
- data/.rubocop +0 -3
- data/.rubocop.yml +0 -26
- data/.ruby-version +0 -1
- data/.simplecov +0 -11
- data/.travis.yml +0 -21
- data/Gemfile +0 -4
- data/Rakefile +0 -18
- data/lib/link_header_parser/parsed_header.rb +0 -70
- data/lib/link_header_parser/parsed_header_collection.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edd4ff4c4ffec2f5a5610c32c6814cd82fc1b6f33308648bac07e3444f5f007b
|
4
|
+
data.tar.gz: 2f533a163609ef49b0e8f44d3ddfe85c2450aedffd6da2ae971cee4b54a22d18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bca6797af5591f2114b141a11aa7f1d1c80c61279fc79dedce4fcba6fa557777c3c2ae635e87012b4a3ce13e43d4ba42c506b274f8ddf6b6631b18e1c71b19d
|
7
|
+
data.tar.gz: db2871789cb01fdcd8b8e8e848320d0ff4c8444381f39a02fdbc24071caf2dce3fed31dc0106c53649c21f57a725348a5c4e1943e759c7be5d21e918a819f4da
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,35 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.2.0 / 20201-04-02
|
4
|
+
|
5
|
+
- Expand supported Ruby versions to include 3.0 (7187878)
|
6
|
+
|
7
|
+
## 2.1.0 / 2020-10-07
|
8
|
+
|
9
|
+
- Update Absolutely dependency to 5.0 (62988c0)
|
10
|
+
|
11
|
+
## 2.0.0 / 2020-05-21
|
12
|
+
|
13
|
+
- **Breaking changes:** Rewrite gem code (5351010)
|
14
|
+
- `LinkHeaderParser.parse` returns `LinkHeadersCollection`
|
15
|
+
- New classes: `LinkHeadersCollection`, `LinkHeader`, and `LinkHeaderParameter`
|
16
|
+
- Renamed collection's `by_relation_type` method to `group_by_relation_type`
|
17
|
+
- **Breaking change:** Update project Ruby version to 2.5.8 and minimum Ruby version to 2.5 (05b2e82)
|
18
|
+
- Update inline documentation and refactor `ParsedHeader` and `ParsedHeaderCollection` classes (31ec43e)
|
19
|
+
|
20
|
+
## 1.0.0 / 2020-05-14
|
21
|
+
|
22
|
+
- Update Absolutely dependency to 4.0 (4b78347)
|
23
|
+
- Update development Ruby version to 2.4.10 (8d26096)
|
24
|
+
- Move development dependencies to `Gemfile` (3f6b5dd)
|
25
|
+
|
26
|
+
## 0.3.0 / 2020-01-20
|
27
|
+
|
28
|
+
- Expand supported Ruby versions to include 2.7 (c55624a)
|
29
|
+
|
3
30
|
## 0.2.0 / 2019-07-02
|
4
31
|
|
5
|
-
- Add support for the `anchor` parameter to `ParsedHeader` exposed via `context` and `context_uri` methods (
|
32
|
+
- Add support for the `anchor` parameter to `ParsedHeader` exposed via `context` and `context_uri` methods (d2dff52)
|
6
33
|
|
7
34
|
## 0.1.0 / 2019-06-06
|
8
35
|
|
data/CONTRIBUTING.md
CHANGED
@@ -8,9 +8,9 @@ There are a couple ways you can help improve link-header-parser-ruby:
|
|
8
8
|
|
9
9
|
## Getting Started
|
10
10
|
|
11
|
-
link-header-parser-ruby is developed using Ruby 2.
|
11
|
+
link-header-parser-ruby is developed using Ruby 2.5.8 and is additionally tested against Ruby 2.6, 2.7, and 3.0 using [CircleCI](https://app.circleci.com/pipelines/github/jgarber623/link-header-parser-ruby).
|
12
12
|
|
13
|
-
Before making changes to link-header-parser-ruby, you'll want to install Ruby 2.
|
13
|
+
Before making changes to link-header-parser-ruby, you'll want to install Ruby 2.5.8. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm). Once you've installed Ruby 2.5.8 using your method of choice, install the project's gems by running:
|
14
14
|
|
15
15
|
```sh
|
16
16
|
bundle install
|
@@ -22,7 +22,7 @@ bundle install
|
|
22
22
|
1. Install development dependencies as outlined above.
|
23
23
|
1. Create a feature branch for the code changes you're looking to make: `git checkout -b my-new-feature`.
|
24
24
|
1. _Write some code!_
|
25
|
-
1. If your changes would benefit from testing, add the necessary tests and verify everything passes by running `
|
25
|
+
1. If your changes would benefit from testing, add the necessary tests and verify everything passes by running `bin/ci`.
|
26
26
|
1. Commit your changes: `git commit -am 'Add some new feature or fix some issue'`. _(See [this excellent article](https://chris.beams.io/posts/git-commit/) for tips on writing useful Git commit messages.)_
|
27
27
|
1. Push the branch to your fork: `git push -u origin my-new-feature`.
|
28
28
|
1. Create a new [pull request][pulls] and we'll review your changes.
|
data/README.md
CHANGED
@@ -2,18 +2,17 @@
|
|
2
2
|
|
3
3
|
**A Ruby gem for parsing HTTP Link headers.**
|
4
4
|
|
5
|
-
[](https://rubygems.org/gems/link-header-parser)
|
6
|
-
[](https://rubygems.org/gems/link-header-parser)
|
7
|
-
[](https://codeclimate.com/github/jgarber623/link-header-parser-ruby/code)
|
5
|
+
[](https://rubygems.org/gems/link-header-parser)
|
6
|
+
[](https://rubygems.org/gems/link-header-parser)
|
7
|
+
[](https://app.circleci.com/pipelines/github/jgarber623/link-header-parser-ruby)
|
8
|
+
[](https://codeclimate.com/github/jgarber623/link-header-parser-ruby)
|
9
|
+
[](https://codeclimate.com/github/jgarber623/link-header-parser-ruby/code)
|
11
10
|
|
12
11
|
## Getting Started
|
13
12
|
|
14
|
-
Before installing and using link-header-parser-ruby, you'll want to have [Ruby](https://www.ruby-lang.org) 2.
|
13
|
+
Before installing and using link-header-parser-ruby, you'll want to have [Ruby](https://www.ruby-lang.org) 2.5 (or newer) installed. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm).
|
15
14
|
|
16
|
-
link-header-parser-ruby is developed using Ruby 2.
|
15
|
+
link-header-parser-ruby is developed using Ruby 2.5.8 and is additionally tested against Ruby 2.6, 2.7, and 3.0 using [CircleCI](https://app.circleci.com/pipelines/github/jgarber623/link-header-parser-ruby).
|
17
16
|
|
18
17
|
## Installation
|
19
18
|
|
@@ -51,82 +50,101 @@ The `parse` method accepts two arguments:
|
|
51
50
|
1. an `Array` of strings representing HTTP Link headers (e.g. `['</>; rel="home"', '</chapters/1>; anchor="#copyright"; rel="license"']`)
|
52
51
|
1. a `String` representing the absolute URL of the resource providing the HTTP Link headers
|
53
52
|
|
54
|
-
In the example above, `collection` is an instance of `
|
53
|
+
In the example above, `collection` is an instance of `LinkHeadersCollection` which includes Ruby's [`Enumerable`](https://ruby-doc.org/core/Enumerable.html) mixin. This mixin allows for use of common methods like `each`, `first`/`last`, and `map`.
|
55
54
|
|
56
55
|
For example, you could retrieve an array of `target_uri`s:
|
57
56
|
|
58
57
|
```ruby
|
59
|
-
puts collection.map(&:target_uri)
|
58
|
+
puts collection.map(&:target_uri)
|
59
|
+
#=> ["https://assets.sixtwothree.org/", "https://fonts.googleapis.com/", "https://fonts.gstatic.com/", "https://sixtwothree.org/webmentions"]
|
60
60
|
```
|
61
61
|
|
62
|
-
### Working with a `
|
62
|
+
### Working with a `LinkHeadersCollection`
|
63
63
|
|
64
|
-
In addition to the included `Enumerable` methods, the following methods may be used to interact with a `
|
64
|
+
In addition to the included `Enumerable` methods, the following methods may be used to interact with a `LinkHeadersCollection`:
|
65
65
|
|
66
66
|
#### The `relation_types` Method
|
67
67
|
|
68
68
|
```ruby
|
69
|
-
puts collection.relation_types
|
69
|
+
puts collection.relation_types
|
70
|
+
#=> ["preconnect", "webmention"]
|
70
71
|
```
|
71
72
|
|
72
|
-
#### The `
|
73
|
+
#### The `group_by_relation_type` Method
|
73
74
|
|
74
|
-
Using the `collection` from above, the `
|
75
|
+
Using the `collection` from above, the `group_by_relation_type` method returns a `Hash`:
|
75
76
|
|
76
77
|
```ruby
|
77
78
|
{
|
78
79
|
preconnect: [
|
79
|
-
#<LinkHeaderParser::
|
80
|
-
#<LinkHeaderParser::
|
81
|
-
#<LinkHeaderParser::
|
80
|
+
#<LinkHeaderParser::LinkHeader target_uri: "https://assets.sixtwothree.org/", relation_types: ["preconnect"]>,
|
81
|
+
#<LinkHeaderParser::LinkHeader target_uri: "https://fonts.googleapis.com/", relation_types: ["preconnect"]>,
|
82
|
+
#<LinkHeaderParser::LinkHeader target_uri: "https://fonts.gstatic.com/", relation_types: ["preconnect"]>
|
82
83
|
],
|
83
84
|
webmention: [
|
84
|
-
#<LinkHeaderParser::
|
85
|
+
#<LinkHeaderParser::LinkHeader target_uri: "https://sixtwothree.org/webmentions", relation_types: ["webmention"]>
|
85
86
|
]
|
86
87
|
}
|
87
88
|
```
|
88
89
|
|
89
|
-
### Working with a `
|
90
|
+
### Working with a `LinkHeader`
|
90
91
|
|
91
|
-
You may interact with one or more `
|
92
|
+
You may interact with one or more `LinkHeader`s in a `LinkHeadersCollection` using the methods outlined below. The naming conventions for these methods draws heavily on the terminology established in [RFC-5988](https://tools.ietf.org/html/rfc5988) and [RFC-8288](https://tools.ietf.org/html/rfc8288).
|
92
93
|
|
93
94
|
#### Link Target ([§ 3.1](https://tools.ietf.org/html/rfc8288#section-3.1))
|
94
95
|
|
95
96
|
```ruby
|
96
|
-
|
97
|
-
parsed_header = LinkHeaderParser.parse(link_headers, base: 'https://example.com/').first
|
97
|
+
link_header = LinkHeaderParser.parse('</index.html>; rel="home"', base: 'https://example.com/').first
|
98
98
|
|
99
|
-
|
100
|
-
|
99
|
+
link_header.target_string
|
100
|
+
#=> "/index.html"
|
101
|
+
|
102
|
+
link_header.target_uri
|
103
|
+
#=> "https://example.com/index.html"
|
101
104
|
```
|
102
105
|
|
103
|
-
The `
|
106
|
+
The `target_string` method returns a string of the value between the opening and closing angle brackets at the beginning of the Link header. The `target_uri` method returns a string representing the resolved URL.
|
104
107
|
|
105
108
|
#### Link Context ([§ 3.2](https://tools.ietf.org/html/rfc8288#section-3.2))
|
106
109
|
|
107
110
|
```ruby
|
108
|
-
|
109
|
-
|
111
|
+
link_header = LinkHeaderParser.parse('</chapters/1>; anchor="#copyright"; rel="license"', base: 'https://example.com/').first
|
112
|
+
|
113
|
+
link_header.context_string
|
114
|
+
#=> "#copyright"
|
110
115
|
|
111
|
-
|
112
|
-
|
116
|
+
link_header.context_uri
|
117
|
+
#=> "https://example.com/chapters/1#copyright"
|
113
118
|
```
|
114
119
|
|
115
|
-
The `anchor` parameter's value may be a fragment identifier (e.g. `#foo`), a relative URL (e.g. `/foo`), or an absolute URL (e.g. `https://context.example.com`). The `
|
120
|
+
The `anchor` parameter's value may be a fragment identifier (e.g. `#foo`), a relative URL (e.g. `/foo`), or an absolute URL (e.g. `https://context.example.com`). The `context_string` method returns the `anchor` parameter's value (when present) and defaults to the `target_string` value. The `context_uri` method returns a string representing the resolved URL.
|
116
121
|
|
117
122
|
#### Relation Type ([§ 3.3](https://tools.ietf.org/html/rfc8288#section-3.3))
|
118
123
|
|
119
124
|
```ruby
|
120
|
-
|
121
|
-
|
125
|
+
link_header = LinkHeaderParser.parse('</chapters/1>; rel="prev start"', base: 'https://example.com/').first
|
126
|
+
|
127
|
+
link_header.relations_string
|
128
|
+
#=> "prev start"
|
122
129
|
|
123
|
-
|
124
|
-
|
130
|
+
link_header.relation_types
|
131
|
+
#=> ["prev", "start"]
|
125
132
|
```
|
126
133
|
|
134
|
+
#### Link Parameters ([Appendix B.3](https://tools.ietf.org/html/rfc8288#appendix-B.3))
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
link_header = LinkHeaderParser.parse('</posts.rss>; rel="alternate"; hreflang="en-US"; title="sixtwothree.org: Posts"; type="application/rss+xml"', base: 'https://sixtwothree.org').first
|
138
|
+
|
139
|
+
link_header.link_parameters
|
140
|
+
#=> [#<LinkHeaderParser::LinkHeaderParameter:0x3fdea54716ac name: "rel", value: "alternate">, #<LinkHeaderParser::LinkHeaderParameter:0x3fdea5471684 name: "hreflang", value: "en-US">, #<LinkHeaderParser::LinkHeaderParameter:0x3fdea5471670 name: "title", value: "sixtwothree.org: Posts">, #<LinkHeaderParser::LinkHeaderParameter:0x3fdea547165c name: "type", value: "application/rss+xml">]
|
141
|
+
```
|
142
|
+
|
143
|
+
Note that the `Array` returned by the `link_parameters` method may include multiple `LinkHeaderParameter`s with the same name depending on the provided Link header. Certain methods on `LinkHeader` will return values from the first occurrence of a parameter name (e.g. `link_header.relations_string`) in accordance with [RFC-8288](https://tools.ietf.org/html/rfc8288).
|
144
|
+
|
127
145
|
## Contributing
|
128
146
|
|
129
|
-
Interested in helping improve link-header-parser-ruby? Awesome! Your help is greatly appreciated. See [CONTRIBUTING.md](https://github.com/jgarber623/link-header-parser-ruby/blob/
|
147
|
+
Interested in helping improve link-header-parser-ruby? Awesome! Your help is greatly appreciated. See [CONTRIBUTING.md](https://github.com/jgarber623/link-header-parser-ruby/blob/main/CONTRIBUTING.md) for details.
|
130
148
|
|
131
149
|
## Acknowledgments
|
132
150
|
|
data/lib/link-header-parser.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
-
require '
|
1
|
+
require 'forwardable'
|
2
2
|
|
3
3
|
require 'absolutely'
|
4
4
|
|
5
5
|
require 'link_header_parser/version'
|
6
6
|
require 'link_header_parser/exceptions'
|
7
7
|
|
8
|
-
require 'link_header_parser/
|
9
|
-
require 'link_header_parser/
|
8
|
+
require 'link_header_parser/link_header'
|
9
|
+
require 'link_header_parser/link_header_parameter'
|
10
|
+
require 'link_header_parser/link_headers_collection'
|
10
11
|
|
11
12
|
module LinkHeaderParser
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# Parse an array of HTTP Link headers
|
14
|
+
#
|
15
|
+
# @param headers [Array<String>]
|
16
|
+
# @param base [String]
|
17
|
+
# @return [LinkHeaderParser::LinkHeadersCollection]
|
18
|
+
def self.parse(*headers, base:)
|
19
|
+
LinkHeadersCollection.new(*headers, base: base)
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module LinkHeaderParser
|
2
|
+
class LinkHeader
|
3
|
+
FIELD_VALUE_REGEXP_PATTERN = /^\s*<\s*(?<target_string>[^>]+)\s*>\s*(?<parameters>;\s*.*)$/.freeze
|
4
|
+
PARAMETERS_REGEXP_PATTERN = /(?<!;)\s*([^;]+)/.freeze
|
5
|
+
|
6
|
+
attr_reader :field_value
|
7
|
+
|
8
|
+
# Create a new parsed Link header
|
9
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2
|
10
|
+
#
|
11
|
+
# @param field_value [String]
|
12
|
+
# @param base [String]
|
13
|
+
def initialize(field_value, base:)
|
14
|
+
raise ArgumentError, "field_value must be a String (given #{field_value.class})" unless field_value.is_a?(String)
|
15
|
+
raise ArgumentError, "base must be a String (given #{base.class})" unless base.is_a?(String)
|
16
|
+
|
17
|
+
@field_value = field_value
|
18
|
+
@base = base
|
19
|
+
end
|
20
|
+
|
21
|
+
# The context URL for this Link header extracted from field_value (or target URL if no context URL is present)
|
22
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.11)
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def context_string
|
26
|
+
@context_string ||= grouped_link_parameters[:anchor]&.first || target_string
|
27
|
+
end
|
28
|
+
|
29
|
+
# The resolved context URL for this Link header
|
30
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.12)
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
def context_uri
|
34
|
+
@context_uri ||= Absolutely.to_abs(base: target_uri, relative: context_string)
|
35
|
+
end
|
36
|
+
|
37
|
+
def inspect
|
38
|
+
format(%(#<#{self.class.name}:%#0x target_uri: #{target_uri.inspect}, relation_types: #{relation_types.inspect}>), object_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
# The parsed parameters for this Link header extracted from field_value
|
42
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.3
|
43
|
+
#
|
44
|
+
# @return [Array<LinkHeaderParser::LinkHeaderParameter>]
|
45
|
+
def link_parameters
|
46
|
+
@link_parameters ||= field_value_match_data[:parameters].scan(PARAMETERS_REGEXP_PATTERN).flatten.map { |parameter| LinkHeaderParameter.new(parameter) }
|
47
|
+
end
|
48
|
+
|
49
|
+
# The relations_string value returned as an Array
|
50
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.10 and Appendix B.2.2.17.1)
|
51
|
+
#
|
52
|
+
# @return [Array<String>]
|
53
|
+
def relation_types
|
54
|
+
@relation_types ||= relations_string.split.map(&:downcase)
|
55
|
+
end
|
56
|
+
|
57
|
+
# The relation types for this Link header extracted from field_value
|
58
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.9)
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
def relations_string
|
62
|
+
@relations_string ||= grouped_link_parameters[:rel]&.first || ''
|
63
|
+
end
|
64
|
+
|
65
|
+
# The target URL for this Link header extracted from field_value
|
66
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.4)
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
def target_string
|
70
|
+
@target_string ||= field_value_match_data[:target_string]
|
71
|
+
end
|
72
|
+
|
73
|
+
# The resolved target URL for this Link header
|
74
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.2 (Appendix B.2.2.8)
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
def target_uri
|
78
|
+
@target_uri ||= Absolutely.to_abs(base: base, relative: target_string)
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Hash{Symbol => String, Array, Hash{Symbol => Array}}]
|
82
|
+
def to_h
|
83
|
+
{
|
84
|
+
target_string: target_string,
|
85
|
+
target_uri: target_uri,
|
86
|
+
context_string: context_string,
|
87
|
+
context_uri: context_uri,
|
88
|
+
relations_string: relations_string,
|
89
|
+
relation_types: relation_types,
|
90
|
+
link_parameters: grouped_link_parameters
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
attr_reader :base
|
97
|
+
|
98
|
+
def field_value_match_data
|
99
|
+
@field_value_match_data ||= field_value.match(FIELD_VALUE_REGEXP_PATTERN)
|
100
|
+
end
|
101
|
+
|
102
|
+
def grouped_link_parameters
|
103
|
+
@grouped_link_parameters ||= link_parameters.map(&:to_a).group_by(&:shift).transform_keys(&:to_sym).transform_values(&:flatten)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module LinkHeaderParser
|
2
|
+
class LinkHeaderParameter
|
3
|
+
PARAMETER_REGEXP_PATTERN = /^(?<name>.+?)(?:="?(?<value>.*?)"?)?$/.freeze
|
4
|
+
|
5
|
+
attr_reader :parameter
|
6
|
+
|
7
|
+
# @param parameter [String]
|
8
|
+
def initialize(parameter)
|
9
|
+
@parameter = parameter
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
format(%(#<#{self.class.name}:%#0x name: #{name.inspect}, value: #{value.inspect}>), object_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.3 (Appendix B.3.2.9)
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
def name
|
20
|
+
@name ||= parameter_match_data[:name].downcase
|
21
|
+
end
|
22
|
+
|
23
|
+
# @see https://tools.ietf.org/html/rfc8288#appendix-B.3 (Appendix B.3.2.8)
|
24
|
+
#
|
25
|
+
# @return [String, nil]
|
26
|
+
def value
|
27
|
+
@value ||= parameter_match_data[:value] || ''
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array<String>]
|
31
|
+
def to_a
|
32
|
+
[name, value]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def parameter_match_data
|
38
|
+
@parameter_match_data ||= parameter.match(PARAMETER_REGEXP_PATTERN)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module LinkHeaderParser
|
2
|
+
class LinkHeadersCollection
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def_delegators :members, :[], :<<, :each, :last, :length, :push
|
8
|
+
|
9
|
+
attr_reader :headers
|
10
|
+
|
11
|
+
# @param headers [Array<String>]
|
12
|
+
# @param base [String]
|
13
|
+
def initialize(*headers, base:)
|
14
|
+
@headers = headers.flatten
|
15
|
+
@base = base
|
16
|
+
|
17
|
+
discrete_headers.each { |header| push(LinkHeader.new(header, base: base)) }
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Hash{Symbol => Array<LinkHeaderParser::LinkHeader>}]
|
21
|
+
def group_by_relation_type
|
22
|
+
relation_types.map do |relation_type|
|
23
|
+
[relation_type, find_all { |member| member.relation_types.include?(relation_type) }]
|
24
|
+
end.to_h.transform_keys(&:to_sym)
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
format(%(#<#{self.class.name}:%#0x headers: #{headers.inspect}, relation_types: #{relation_types.inspect}>), object_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Array<String>]
|
32
|
+
def relation_types
|
33
|
+
@relation_types ||= flat_map(&:relation_types).uniq.sort
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :base
|
39
|
+
|
40
|
+
def discrete_headers
|
41
|
+
@discrete_headers ||= headers.flat_map { |header| header.split(/,(?=[\s|<])/) }.map(&:strip)
|
42
|
+
end
|
43
|
+
|
44
|
+
def members
|
45
|
+
@members ||= []
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/link-header-parser.gemspec
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
|
4
|
-
require 'link_header_parser/version'
|
1
|
+
require_relative 'lib/link_header_parser/version'
|
5
2
|
|
6
3
|
Gem::Specification.new do |spec|
|
7
|
-
spec.required_ruby_version =
|
4
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 4')
|
8
5
|
|
9
6
|
spec.name = 'link-header-parser'
|
10
7
|
spec.version = LinkHeaderParser::VERSION
|
@@ -16,23 +13,14 @@ Gem::Specification.new do |spec|
|
|
16
13
|
spec.homepage = 'https://github.com/jgarber623/link-header-parser-ruby'
|
17
14
|
spec.license = 'MIT'
|
18
15
|
|
19
|
-
spec.files =
|
16
|
+
spec.files = Dir['lib/**/*'].reject { |f| File.directory?(f) }
|
17
|
+
spec.files += %w[LICENSE CHANGELOG.md CONTRIBUTING.md README.md]
|
18
|
+
spec.files += %w[link-header-parser.gemspec]
|
20
19
|
|
21
20
|
spec.require_paths = ['lib']
|
22
21
|
|
23
|
-
spec.metadata = {
|
24
|
-
|
25
|
-
'changelog_uri' => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
|
26
|
-
}
|
27
|
-
|
28
|
-
spec.add_development_dependency 'rake', '~> 12.3'
|
29
|
-
spec.add_development_dependency 'reek', '~> 5.4'
|
30
|
-
spec.add_development_dependency 'rspec', '~> 3.8'
|
31
|
-
spec.add_development_dependency 'rubocop', '~> 0.72.0'
|
32
|
-
spec.add_development_dependency 'rubocop-performance', '~> 1.3'
|
33
|
-
spec.add_development_dependency 'rubocop-rspec', '~> 1.33'
|
34
|
-
spec.add_development_dependency 'simplecov', '~> 0.16.1'
|
35
|
-
spec.add_development_dependency 'simplecov-console', '~> 0.5.0'
|
22
|
+
spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
|
23
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
|
36
24
|
|
37
|
-
spec.add_runtime_dependency 'absolutely', '~>
|
25
|
+
spec.add_runtime_dependency 'absolutely', '~> 5.1'
|
38
26
|
end
|
metadata
CHANGED
@@ -1,141 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: link-header-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Garber
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rake
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '12.3'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '12.3'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: reek
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '5.4'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '5.4'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '3.8'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '3.8'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rubocop
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.72.0
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 0.72.0
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rubocop-performance
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '1.3'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '1.3'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop-rspec
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.33'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1.33'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: simplecov
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 0.16.1
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 0.16.1
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: simplecov-console
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.5.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 0.5.0
|
125
13
|
- !ruby/object:Gem::Dependency
|
126
14
|
name: absolutely
|
127
15
|
requirement: !ruby/object:Gem::Requirement
|
128
16
|
requirements:
|
129
17
|
- - "~>"
|
130
18
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
19
|
+
version: '5.1'
|
132
20
|
type: :runtime
|
133
21
|
prerelease: false
|
134
22
|
version_requirements: !ruby/object:Gem::Requirement
|
135
23
|
requirements:
|
136
24
|
- - "~>"
|
137
25
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
26
|
+
version: '5.1'
|
139
27
|
description: Parse HTTP Link headers.
|
140
28
|
email:
|
141
29
|
- jason@sixtwothree.org
|
@@ -143,25 +31,15 @@ executables: []
|
|
143
31
|
extensions: []
|
144
32
|
extra_rdoc_files: []
|
145
33
|
files:
|
146
|
-
- ".editorconfig"
|
147
|
-
- ".gitignore"
|
148
|
-
- ".reek.yml"
|
149
|
-
- ".rspec"
|
150
|
-
- ".rubocop"
|
151
|
-
- ".rubocop.yml"
|
152
|
-
- ".ruby-version"
|
153
|
-
- ".simplecov"
|
154
|
-
- ".travis.yml"
|
155
34
|
- CHANGELOG.md
|
156
35
|
- CONTRIBUTING.md
|
157
|
-
- Gemfile
|
158
36
|
- LICENSE
|
159
37
|
- README.md
|
160
|
-
- Rakefile
|
161
38
|
- lib/link-header-parser.rb
|
162
39
|
- lib/link_header_parser/exceptions.rb
|
163
|
-
- lib/link_header_parser/
|
164
|
-
- lib/link_header_parser/
|
40
|
+
- lib/link_header_parser/link_header.rb
|
41
|
+
- lib/link_header_parser/link_header_parameter.rb
|
42
|
+
- lib/link_header_parser/link_headers_collection.rb
|
165
43
|
- lib/link_header_parser/version.rb
|
166
44
|
- link-header-parser.gemspec
|
167
45
|
homepage: https://github.com/jgarber623/link-header-parser-ruby
|
@@ -169,8 +47,8 @@ licenses:
|
|
169
47
|
- MIT
|
170
48
|
metadata:
|
171
49
|
bug_tracker_uri: https://github.com/jgarber623/link-header-parser-ruby/issues
|
172
|
-
changelog_uri: https://github.com/jgarber623/link-header-parser-ruby/blob/
|
173
|
-
post_install_message:
|
50
|
+
changelog_uri: https://github.com/jgarber623/link-header-parser-ruby/blob/v2.2.0/CHANGELOG.md
|
51
|
+
post_install_message:
|
174
52
|
rdoc_options: []
|
175
53
|
require_paths:
|
176
54
|
- lib
|
@@ -178,18 +56,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
178
56
|
requirements:
|
179
57
|
- - ">="
|
180
58
|
- !ruby/object:Gem::Version
|
181
|
-
version: '2.
|
59
|
+
version: '2.5'
|
182
60
|
- - "<"
|
183
61
|
- !ruby/object:Gem::Version
|
184
|
-
version: '
|
62
|
+
version: '4'
|
185
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
64
|
requirements:
|
187
65
|
- - ">="
|
188
66
|
- !ruby/object:Gem::Version
|
189
67
|
version: '0'
|
190
68
|
requirements: []
|
191
|
-
rubygems_version: 3.
|
192
|
-
signing_key:
|
69
|
+
rubygems_version: 3.1.2
|
70
|
+
signing_key:
|
193
71
|
specification_version: 4
|
194
72
|
summary: Parse HTTP Link headers.
|
195
73
|
test_files: []
|
data/.editorconfig
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
2
|
-
root = true
|
3
|
-
|
4
|
-
[*]
|
5
|
-
charset = utf-8
|
6
|
-
end_of_line = lf
|
7
|
-
insert_final_newline = true
|
8
|
-
indent_size = 2
|
9
|
-
indent_style = space
|
10
|
-
trim_trailing_whitespace = true
|
11
|
-
|
12
|
-
[*.md]
|
13
|
-
indent_size = 4
|
14
|
-
indent_style = tab
|
data/.gitignore
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
/.config
|
4
|
-
/coverage/
|
5
|
-
/InstalledFiles
|
6
|
-
/pkg/
|
7
|
-
/spec/reports/
|
8
|
-
/spec/examples.txt
|
9
|
-
/test/tmp/
|
10
|
-
/test/version_tmp/
|
11
|
-
/tmp/
|
12
|
-
|
13
|
-
# Used by dotenv library to load environment variables.
|
14
|
-
# .env
|
15
|
-
|
16
|
-
# Documentation cache and generated files:
|
17
|
-
/.yardoc/
|
18
|
-
/_yardoc/
|
19
|
-
/doc/
|
20
|
-
/rdoc/
|
21
|
-
|
22
|
-
# Environment normalization:
|
23
|
-
/.bundle/
|
24
|
-
/vendor/bundle
|
25
|
-
/lib/bundler/man/
|
26
|
-
|
27
|
-
# for a library or gem, you might want to ignore these files since the code is
|
28
|
-
# intended to run in multiple environments; otherwise, check them in:
|
29
|
-
Gemfile.lock
|
30
|
-
# .ruby-version
|
31
|
-
# .ruby-gemset
|
32
|
-
|
33
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
-
.rvmrc
|
data/.reek.yml
DELETED
data/.rspec
DELETED
data/.rubocop
DELETED
data/.rubocop.yml
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require:
|
2
|
-
- rubocop-performance
|
3
|
-
- rubocop-rspec
|
4
|
-
|
5
|
-
Layout/AlignHash:
|
6
|
-
EnforcedHashRocketStyle: table
|
7
|
-
|
8
|
-
Metrics/LineLength:
|
9
|
-
Enabled: false
|
10
|
-
|
11
|
-
Metrics/ModuleLength:
|
12
|
-
Exclude:
|
13
|
-
- spec/support/**/*.rb
|
14
|
-
|
15
|
-
Naming/FileName:
|
16
|
-
Exclude:
|
17
|
-
- lib/link-header-parser.rb
|
18
|
-
|
19
|
-
Style/Documentation:
|
20
|
-
Enabled: false
|
21
|
-
|
22
|
-
Style/FrozenStringLiteralComment:
|
23
|
-
Enabled: false
|
24
|
-
|
25
|
-
Style/SymbolArray:
|
26
|
-
Enabled: false
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.4.6
|
data/.simplecov
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'simplecov-console'
|
2
|
-
|
3
|
-
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
4
|
-
|
5
|
-
if RSpec.configuration.files_to_run.length > 1
|
6
|
-
formatters << SimpleCov::Formatter::Console
|
7
|
-
end
|
8
|
-
|
9
|
-
SimpleCov.start do
|
10
|
-
formatter SimpleCov::Formatter::MultiFormatter.new(formatters)
|
11
|
-
end
|
data/.travis.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- 2.4.6
|
4
|
-
- 2.5.5
|
5
|
-
- 2.6.3
|
6
|
-
cache:
|
7
|
-
- bundler
|
8
|
-
before_install:
|
9
|
-
- gem update --system
|
10
|
-
- gem install bundler
|
11
|
-
before_script:
|
12
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
13
|
-
- chmod +x ./cc-test-reporter
|
14
|
-
- ./cc-test-reporter before-build
|
15
|
-
after_script:
|
16
|
-
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
17
|
-
notifications:
|
18
|
-
email: false
|
19
|
-
slack:
|
20
|
-
rooms:
|
21
|
-
secure: ZV5G4LIK9OXRXkXt3iC53QD1uVWmThzETj8CallRoZgGfUKfzzMjx2V7NqJLwkmFkaK9y/flt/bRVMVqkH60GY0Gq6YeS9zuKEWJYesC6+aWQa6scKaxgewLdfYth3ijMS91XbPKECbFj0LOs1WPTfqYDsdPpOnH2RBWUO6lx8ID4DZtvi7kMhcY2+K21Q3/3gW9y919KHSCppM24EsyIbkAlFce5RjXn5WmfyTOTyTrxbHyByFr3SSTGdyO3KK0Fa4hhKNC2pa5WmlLHvZ/c5P7MYf1Eo+Rji5I0QY3pcGOIvbK0xBBnXnGI6Zfp088evElGpw8qgUdkR03QbxjTYANdN6mlk9DvnHqPWjI6OalF3SA7PP9mYjKVb2THDPqWOAvqYdMrrLylduWfdCzpxk4Z13DwF6rYSRgz3juKeKx80rhcAFmptLAC3uzQxgSgKoj9xZbbcYqhh/JQL9lNBZYJyLO5M0fOzrEDbLyNrWFYzUgKYgxRAOLWhJ8V2FlN3oR2cXXcf6vmlpPYfoCA0a8Ig82Htapan0JEhNEU6sS1ctdS7NegccEB9P0V5hUDy3AooaqCy8gFYE3TENYI1vwrevo5vqtNffR1PXTsliGe/gIIeFET6H2IJ+HYG9DefMHwYIR97enMFe50PauNGqdHS9kCoUV59r1PDOBJuU=
|
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'bundler/gem_tasks'
|
2
|
-
|
3
|
-
require 'reek/rake/task'
|
4
|
-
require 'rspec/core/rake_task'
|
5
|
-
require 'rubocop/rake_task'
|
6
|
-
|
7
|
-
Reek::Rake::Task.new do |task|
|
8
|
-
task.fail_on_error = false
|
9
|
-
task.source_files = FileList['**/*.rb'].exclude('vendor/**/*.rb')
|
10
|
-
end
|
11
|
-
|
12
|
-
RSpec::Core::RakeTask.new
|
13
|
-
|
14
|
-
RuboCop::RakeTask.new do |task|
|
15
|
-
task.fail_on_error = false
|
16
|
-
end
|
17
|
-
|
18
|
-
task default: [:rubocop, :reek, :spec]
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module LinkHeaderParser
|
2
|
-
class ParsedHeader
|
3
|
-
attr_reader :header
|
4
|
-
|
5
|
-
def initialize(header, base:)
|
6
|
-
raise ArgumentError, "header must be a String (given #{header.class})" unless header.is_a?(String)
|
7
|
-
raise ArgumentError, "base must be a String (given #{base.class})" unless base.is_a?(String)
|
8
|
-
|
9
|
-
@header = header
|
10
|
-
@base = base
|
11
|
-
end
|
12
|
-
|
13
|
-
# https://tools.ietf.org/html/rfc8288#section-3.2
|
14
|
-
def context
|
15
|
-
@context ||= parameters.anchor || target
|
16
|
-
end
|
17
|
-
|
18
|
-
def context_uri
|
19
|
-
@context_uri ||= Absolutely.to_abs(base: target_uri, relative: context)
|
20
|
-
end
|
21
|
-
|
22
|
-
def inspect
|
23
|
-
format(%(#<#{self.class.name}:%#0x @header="#{header.gsub('"', '\"')}">), object_id)
|
24
|
-
end
|
25
|
-
|
26
|
-
def parameters
|
27
|
-
@parameters ||= OpenStruct.new(header_attributes)
|
28
|
-
end
|
29
|
-
|
30
|
-
def relation_types
|
31
|
-
@relation_types ||= relations&.split(' ') || nil
|
32
|
-
end
|
33
|
-
|
34
|
-
# https://tools.ietf.org/html/rfc8288#section-3.3
|
35
|
-
def relations
|
36
|
-
@relations ||= parameters.rel || nil
|
37
|
-
end
|
38
|
-
|
39
|
-
# https://tools.ietf.org/html/rfc8288#section-3.1
|
40
|
-
def target
|
41
|
-
@target ||= header_match_data[:target]
|
42
|
-
end
|
43
|
-
|
44
|
-
def target_uri
|
45
|
-
@target_uri ||= Absolutely.to_abs(base: @base, relative: target)
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_h
|
49
|
-
{
|
50
|
-
target: target,
|
51
|
-
target_uri: target_uri,
|
52
|
-
context: context,
|
53
|
-
context_uri: context_uri,
|
54
|
-
relations: relations,
|
55
|
-
relation_types: relation_types,
|
56
|
-
parameters: parameters.to_h
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def header_attributes
|
63
|
-
@header_attributes ||= header_match_data[:attributes].tr('"', '').split(';').map { |tuple| tuple.split('=').map(&:strip) }.sort.to_h
|
64
|
-
end
|
65
|
-
|
66
|
-
def header_match_data
|
67
|
-
@header_match_data ||= header.match(/^<\s*(?<target>[^>]+)\s*>\s*;\s*(?<attributes>.*)$/)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
module LinkHeaderParser
|
2
|
-
class ParsedHeaderCollection
|
3
|
-
include Enumerable
|
4
|
-
|
5
|
-
attr_reader :headers
|
6
|
-
|
7
|
-
def initialize(*headers, base:)
|
8
|
-
@headers = headers.flatten
|
9
|
-
@base = base
|
10
|
-
end
|
11
|
-
|
12
|
-
def by_relation_type
|
13
|
-
@by_relation_type ||= OpenStruct.new(mapped_relation_types)
|
14
|
-
end
|
15
|
-
|
16
|
-
def each
|
17
|
-
return to_enum unless block_given?
|
18
|
-
|
19
|
-
parsed_headers.each { |parsed_header| yield parsed_header }
|
20
|
-
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def inspect
|
25
|
-
format(%(#<#{self.class.name}:%#0x @headers=#{headers}>), object_id)
|
26
|
-
end
|
27
|
-
|
28
|
-
def last
|
29
|
-
@last ||= parsed_headers[-1]
|
30
|
-
end
|
31
|
-
|
32
|
-
def length
|
33
|
-
@length ||= parsed_headers.length
|
34
|
-
end
|
35
|
-
|
36
|
-
def relation_types
|
37
|
-
@relation_types ||= parsed_headers.map(&:relation_types).flatten.uniq.sort
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def find_all_by_relation_type(relation_type)
|
43
|
-
find_all { |parsed_header| parsed_header.relation_types.include?(relation_type) }
|
44
|
-
end
|
45
|
-
|
46
|
-
def mapped_relation_types
|
47
|
-
@mapped_relation_types ||= relation_types.map { |relation_type| [relation_type, find_all_by_relation_type(relation_type)] }.to_h
|
48
|
-
end
|
49
|
-
|
50
|
-
def parsed_headers
|
51
|
-
@parsed_headers ||= uniq_headers.map { |header| ParsedHeader.new(header, base: @base) }
|
52
|
-
end
|
53
|
-
|
54
|
-
def uniq_headers
|
55
|
-
@uniq_headers ||= headers.map { |header| header.split(/,(?=[\s|<])/) }.flatten.map(&:strip)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|