accept_headers 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +3 -33
- data/lib/accept_headers.rb +0 -2
- data/lib/accept_headers/encoding/negotiator.rb +1 -1
- data/lib/accept_headers/middleware.rb +17 -0
- data/lib/accept_headers/version.rb +1 -1
- metadata +2 -7
- data/lib/accept_headers/charset.rb +0 -45
- data/lib/accept_headers/charset/negotiator.rb +0 -27
- data/spec/charset/negotiator_spec.rb +0 -73
- data/spec/charset_spec.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a140173043fff3155b04a77f622823cf12838bc5
|
4
|
+
data.tar.gz: 4dc92d7058528b3a06766be6f0e9a3dfb2408b84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 597d9faad4500046b88f07648c1372120a3c008734c7f100a098c7d2ecc568ec4bb335c1a2d94708729ef0669247a136be62491680655e52bbaae5b22155f13c
|
7
|
+
data.tar.gz: 008ad53a88a1bc15b33564dc68361e116aa19c432ccf09c49529773ca293cb2f5fc7e8804562b594d5a801e2c90750ada349ba74029bf5c27335ee743b5bae02
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -9,9 +9,9 @@
|
|
9
9
|
Some features of the library are:
|
10
10
|
|
11
11
|
* Strict adherence to [RFC 2616][rfc], specifically [section 14][rfc-sec14]
|
12
|
-
* Full support for the [Accept][rfc-sec14-1], [Accept-
|
13
|
-
|
14
|
-
|
12
|
+
* Full support for the [Accept][rfc-sec14-1], [Accept-Encoding][rfc-sec14-3],
|
13
|
+
and [Accept-Language][rfc-sec14-4] HTTP request headers
|
14
|
+
* `Accept-Charset` is not supported because it's [obsolete](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation#The_Accept-Charset.3A_header).
|
15
15
|
* A comprehensive [spec suite][spec] that covers many edge cases
|
16
16
|
|
17
17
|
This library is optimistic when parsing headers. If a specific media type, encoding, charset, or language can't be parsed, is in an invalid format, or contains invalid characters, it will skip that specific entry when constructing the sorted list. If a `q` value can't be read or is in the wrong format (more than 3 decimal places), it will default it to `0.001` so it still has a chance to match. Lack of an explicit `q` value of course defaults to 1.
|
@@ -19,7 +19,6 @@ This library is optimistic when parsing headers. If a specific media type, encod
|
|
19
19
|
[rfc]: http://www.w3.org/Protocols/rfc2616/rfc2616.html
|
20
20
|
[rfc-sec14]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
21
21
|
[rfc-sec14-1]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
22
|
-
[rfc-sec14-2]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2
|
23
22
|
[rfc-sec14-3]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
|
24
23
|
[rfc-sec14-4]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
25
24
|
[spec]: http://github.com/kamui/accept_headers/tree/master/spec/
|
@@ -72,35 +71,6 @@ media_type.negotiate('text/html')
|
|
72
71
|
AcceptHeaders::MediaType.new('text', 'html', params: { 'level' => '1' })
|
73
72
|
```
|
74
73
|
|
75
|
-
### Accept-Charset
|
76
|
-
|
77
|
-
`AcceptHeader::Charset::Negotiator`:
|
78
|
-
|
79
|
-
```ruby
|
80
|
-
charsets = AcceptHeaders::Charset::Negotiator.new("us-ascii; q=0.5, iso-8859-1, utf-8; q=0.8, macintosh")
|
81
|
-
|
82
|
-
charsets.list
|
83
|
-
|
84
|
-
# Returns:
|
85
|
-
|
86
|
-
[
|
87
|
-
AcceptHeaders::Charset.new('iso-8859-1'),
|
88
|
-
AcceptHeaders::Charset.new('macintosh'),
|
89
|
-
AcceptHeaders::Charset.new('utf-8', q: 0.8),
|
90
|
-
AcceptHeaders::Charset.new('us-ascii', q: 0.5)
|
91
|
-
]
|
92
|
-
```
|
93
|
-
|
94
|
-
`#negotiate`:
|
95
|
-
|
96
|
-
```ruby
|
97
|
-
charsets.negotiate('iso-8859-1')
|
98
|
-
|
99
|
-
# Returns:
|
100
|
-
|
101
|
-
AcceptHeaders::Charset.new('iso-8859-1')
|
102
|
-
```
|
103
|
-
|
104
74
|
### Accept-Encoding
|
105
75
|
|
106
76
|
`AcceptHeader::Charset::Encoding`:
|
data/lib/accept_headers.rb
CHANGED
@@ -11,7 +11,7 @@ module AcceptHeaders
|
|
11
11
|
header = original_header.dup
|
12
12
|
header.sub!(/\AAccept-Encoding:\s*/, '')
|
13
13
|
header.strip!
|
14
|
-
return [
|
14
|
+
return [Encoding.new] if header.empty?
|
15
15
|
encodings = []
|
16
16
|
header.split(',').each do |entry|
|
17
17
|
encoding_arr = entry.split(';', 2)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "accept_headers"
|
2
|
+
|
3
|
+
module AcceptHeaders
|
4
|
+
class Middleware
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env["accept_headers.media_types"] = MediaType::Negotiator.new(env["HTTP_ACCEPT"])
|
11
|
+
env["accept_headers.encodings"] = Encoding::Negotiator.new(env["HTTP_ACCEPT_ENCODING"])
|
12
|
+
env["accept_headers.languages"] = Language::Negotiator.new(env["HTTP_ACCEPT_LANGUAGE"])
|
13
|
+
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: accept_headers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jack Chu
|
@@ -99,18 +99,15 @@ files:
|
|
99
99
|
- accept_headers.gemspec
|
100
100
|
- lib/accept_headers.rb
|
101
101
|
- lib/accept_headers/acceptable.rb
|
102
|
-
- lib/accept_headers/charset.rb
|
103
|
-
- lib/accept_headers/charset/negotiator.rb
|
104
102
|
- lib/accept_headers/encoding.rb
|
105
103
|
- lib/accept_headers/encoding/negotiator.rb
|
106
104
|
- lib/accept_headers/language.rb
|
107
105
|
- lib/accept_headers/language/negotiator.rb
|
108
106
|
- lib/accept_headers/media_type.rb
|
109
107
|
- lib/accept_headers/media_type/negotiator.rb
|
108
|
+
- lib/accept_headers/middleware.rb
|
110
109
|
- lib/accept_headers/negotiatable.rb
|
111
110
|
- lib/accept_headers/version.rb
|
112
|
-
- spec/charset/negotiator_spec.rb
|
113
|
-
- spec/charset_spec.rb
|
114
111
|
- spec/encoding/negotiator_spec.rb
|
115
112
|
- spec/encoding_spec.rb
|
116
113
|
- spec/language/negotiator_spec.rb
|
@@ -145,8 +142,6 @@ specification_version: 4
|
|
145
142
|
summary: A ruby library that does content negotiation and parses and sorts http accept
|
146
143
|
headers.
|
147
144
|
test_files:
|
148
|
-
- spec/charset/negotiator_spec.rb
|
149
|
-
- spec/charset_spec.rb
|
150
145
|
- spec/encoding/negotiator_spec.rb
|
151
146
|
- spec/encoding_spec.rb
|
152
147
|
- spec/language/negotiator_spec.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require "accept_headers/acceptable"
|
2
|
-
|
3
|
-
module AcceptHeaders
|
4
|
-
class Charset
|
5
|
-
include Comparable
|
6
|
-
include Acceptable
|
7
|
-
|
8
|
-
attr_reader :charset
|
9
|
-
|
10
|
-
def initialize(charset = '*', q: 1.0)
|
11
|
-
self.charset = charset
|
12
|
-
self.q = q
|
13
|
-
end
|
14
|
-
|
15
|
-
def <=>(other)
|
16
|
-
q <=> other.q
|
17
|
-
end
|
18
|
-
|
19
|
-
def charset=(value)
|
20
|
-
@charset = value.strip.downcase
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_h
|
24
|
-
{
|
25
|
-
charset: charset,
|
26
|
-
q: q
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
qvalue = (q == 0 || q == 1) ? q.to_i : q
|
32
|
-
"#{charset};q=#{qvalue}"
|
33
|
-
end
|
34
|
-
|
35
|
-
def match(other)
|
36
|
-
if charset == other.charset
|
37
|
-
true
|
38
|
-
elsif other.charset == '*'
|
39
|
-
true
|
40
|
-
else
|
41
|
-
false
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require "accept_headers/charset"
|
2
|
-
require "accept_headers/negotiatable"
|
3
|
-
|
4
|
-
module AcceptHeaders
|
5
|
-
class Charset
|
6
|
-
class Negotiator
|
7
|
-
include Negotiatable
|
8
|
-
|
9
|
-
private
|
10
|
-
def parse(original_header)
|
11
|
-
header = original_header.dup
|
12
|
-
header.sub!(/\AAccept-Charset:\s*/, '')
|
13
|
-
header.strip!
|
14
|
-
return [Charset.new('iso-8859-5', q: 1)] if header.empty?
|
15
|
-
charsets = []
|
16
|
-
header.split(',').each do |entry|
|
17
|
-
charset_arr = entry.split(';', 2)
|
18
|
-
next if charset_arr[0].nil?
|
19
|
-
charset = TOKEN_PATTERN.match(charset_arr[0])
|
20
|
-
next if charset.nil?
|
21
|
-
charsets << Charset.new(charset[:token], q: parse_q(charset_arr[1]))
|
22
|
-
end
|
23
|
-
charsets.sort! { |x,y| y <=> x }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
require_relative "../spec_helper"
|
2
|
-
|
3
|
-
module AcceptHeaders
|
4
|
-
class Charset
|
5
|
-
describe Negotiator do
|
6
|
-
subject do
|
7
|
-
AcceptHeaders::Charset::Negotiator
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "parsing an accept header" do
|
11
|
-
it "returns a sorted array of charsets" do
|
12
|
-
subject.new("*; q=0.2, unicode-1-1").list.must_equal [
|
13
|
-
Charset.new('unicode-1-1'),
|
14
|
-
Charset.new('*', q: 0.2)
|
15
|
-
]
|
16
|
-
|
17
|
-
subject.new("us-ascii; q=0.5, iso-8859-1, utf-8; q=0.8, macintosh").list.must_equal [
|
18
|
-
Charset.new('iso-8859-1'),
|
19
|
-
Charset.new('macintosh'),
|
20
|
-
Charset.new('utf-8', q: 0.8),
|
21
|
-
Charset.new('us-ascii', q: 0.5)
|
22
|
-
]
|
23
|
-
end
|
24
|
-
|
25
|
-
it "sets charset to * when the accept-charset header is empty" do
|
26
|
-
subject.new('').list.must_equal [
|
27
|
-
Charset.new('*')
|
28
|
-
]
|
29
|
-
end
|
30
|
-
|
31
|
-
it "defaults q to 1 if it's not explicitly specified" do
|
32
|
-
subject.new("iso-8859-1").list.must_equal [
|
33
|
-
Charset.new('iso-8859-1', q: 1.0)
|
34
|
-
]
|
35
|
-
end
|
36
|
-
|
37
|
-
it "strips whitespace from between charsets" do
|
38
|
-
subject.new("\tunicode-1-1\r,\niso-8859-1\s").list.must_equal [
|
39
|
-
Charset.new('unicode-1-1'),
|
40
|
-
Charset.new('iso-8859-1')
|
41
|
-
]
|
42
|
-
end
|
43
|
-
|
44
|
-
it "strips whitespace around q" do
|
45
|
-
subject.new("iso-8859-1;\tq\r=\n1, unicode-1-1;q=0.8\n").list.must_equal [
|
46
|
-
Charset.new('iso-8859-1'),
|
47
|
-
Charset.new('unicode-1-1', q: 0.8)
|
48
|
-
]
|
49
|
-
end
|
50
|
-
|
51
|
-
it "has a q value of 0.001 when parsed q is invalid" do
|
52
|
-
subject.new("iso-8859-1;q=x").list.must_equal [
|
53
|
-
Charset.new('iso-8859-1', q: 0.001)
|
54
|
-
]
|
55
|
-
end
|
56
|
-
|
57
|
-
it "skips invalid character sets" do
|
58
|
-
subject.new("iso-8859-1, @unicode-1-1").list.must_equal [
|
59
|
-
Charset.new('iso-8859-1', q: 1)
|
60
|
-
]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "negotiate supported charsets" do
|
65
|
-
it "returns a best matching charset" do
|
66
|
-
match = Charset.new('iso-8859-1')
|
67
|
-
n = subject.new('us-ascii; q=0.5, iso-8859-1, utf-8; q=0.8, macintosh')
|
68
|
-
n.negotiate('iso-8859-1').must_equal match
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/spec/charset_spec.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
require_relative "spec_helper"
|
2
|
-
|
3
|
-
module AcceptHeaders
|
4
|
-
describe Charset do
|
5
|
-
subject do
|
6
|
-
AcceptHeaders::Charset
|
7
|
-
end
|
8
|
-
|
9
|
-
it "defaults charset to *" do
|
10
|
-
subject.new.charset.must_equal '*'
|
11
|
-
end
|
12
|
-
|
13
|
-
it "strips and downcases the charset" do
|
14
|
-
subject.new("\t\nISO-8859-1\s\r").charset.must_equal "iso-8859-1"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "optionally supports a q argument" do
|
18
|
-
subject.new('iso-8859-1', q: 0.8).q.must_equal 0.8
|
19
|
-
end
|
20
|
-
|
21
|
-
it "compares on q value all other values remaining equal" do
|
22
|
-
subject.new(q: 0.514).must_be :>, subject.new(q: 0.1)
|
23
|
-
subject.new(q: 0).must_be :<, subject.new(q: 1)
|
24
|
-
subject.new(q: 0.9).must_equal subject.new(q: 0.9)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "raises an InvalidQError if q can't be converted to a float" do
|
28
|
-
e = -> do
|
29
|
-
subject.new('iso-8859-1', q: 'a')
|
30
|
-
end.must_raise Charset::InvalidQError
|
31
|
-
|
32
|
-
e.message.must_equal 'invalid value for Float(): "a"'
|
33
|
-
|
34
|
-
subject.new('iso-8859-1', q: '1')
|
35
|
-
end
|
36
|
-
|
37
|
-
it "raises an InvalidQError unless q value is between 0 and 1" do
|
38
|
-
[-1.0, -0.1, 1.1].each do |q|
|
39
|
-
e = -> do
|
40
|
-
subject.new('iso-8859-1', q: q)
|
41
|
-
end.must_raise Charset::InvalidQError
|
42
|
-
|
43
|
-
e.message.must_equal "q must be between 0 and 1"
|
44
|
-
end
|
45
|
-
|
46
|
-
subject.new('iso-8859-1', q: 1)
|
47
|
-
subject.new('unicode-1-1', q: 0)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "raises an InvalidQError if q has more than a precision of 3" do
|
51
|
-
e = -> do
|
52
|
-
subject.new('iso-8859-1', q: 0.1234)
|
53
|
-
end.must_raise Charset::InvalidQError
|
54
|
-
|
55
|
-
e.message.must_equal "q must be at most 3 decimal places"
|
56
|
-
|
57
|
-
subject.new('iso-8859-1', q: 0.123)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "converts to hash" do
|
61
|
-
subject.new('iso-8859-1').to_h.must_equal({
|
62
|
-
charset: 'iso-8859-1',
|
63
|
-
q: 1.0
|
64
|
-
})
|
65
|
-
end
|
66
|
-
|
67
|
-
it "convers to string" do
|
68
|
-
s = subject.new('iso-8859-1', q: 0.9).to_s
|
69
|
-
s.must_equal "iso-8859-1;q=0.9"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|