http-negotiate 0.1.2 → 0.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/.yardopts +5 -0
- data/http-negotiate.gemspec +1 -1
- data/lib/http/negotiate/version.rb +1 -1
- data/lib/http/negotiate.rb +71 -37
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c40df3f0c699e99b0f45c3af71e19e5461878bddecf1a8a28a4125965cc05c9
|
4
|
+
data.tar.gz: 58dfdd11e0a9b119f5e84bdb24e8d2d28145e91d7a8fa3d5d3067572d1c2980e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0610a598b694dfa3a147257e160dfbfafcde951715ff7329f489b22e097490e2999f84a8401ef6019183f30fbbdbe01c31c4daf7dd9abcab34402add0a1f96bc
|
7
|
+
data.tar.gz: b3a19ba49afe90cd32aba42046ec57af147bb1a12f7087102fed03e5520c30cc33fecc41785a226cf7a5680298adcb59ea2b14a9bcd6950db3b2148109a070be
|
data/.yardopts
ADDED
data/http-negotiate.gemspec
CHANGED
@@ -31,5 +31,5 @@ Gem::Specification.new do |spec|
|
|
31
31
|
# dev/test dependencies
|
32
32
|
spec.add_development_dependency 'bundler', '~> 2.2'
|
33
33
|
spec.add_development_dependency 'rake', '~> 13.0'
|
34
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
34
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
35
35
|
end
|
data/lib/http/negotiate.rb
CHANGED
@@ -13,32 +13,31 @@ module HTTP::Negotiate
|
|
13
13
|
|
14
14
|
public
|
15
15
|
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# `gzip`, not like `utf-8`: that's "charset")
|
27
|
-
# * size is the number of bytes, an integer
|
16
|
+
# Return a parsed representation of the relevant header
|
17
|
+
# set. Translates `Accept-*` (`HTTP_ACCEPT_*`) into lower-case
|
18
|
+
# symbols, so `Accept-Language` or `HTTP_ACCEPT_LANGUAGE` becomes
|
19
|
+
# `:language`. Same for `:charset`, and `:encoding`, etc., save for
|
20
|
+
# plain `Accept` which is translated to `:type`. The parameter
|
21
|
+
# `:add_langs` will supplement `Accept-Language` assertions of
|
22
|
+
# specific languages with their more generic counterparts, if not
|
23
|
+
# already present in the header, with a slightly lower quality
|
24
|
+
# score, e.g. `en-us` adds `en;q=0.999`, `zh-cn;q=0.8` adds
|
25
|
+
# `zh;q=0.799`.
|
28
26
|
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
27
|
+
# @param request [Hash, Rack::Request, #env] Anything roughly a hash
|
28
|
+
# of headers
|
29
|
+
# @param add_langs [false, true] whether to supplement language tags
|
32
30
|
#
|
33
|
-
# @
|
34
|
-
# @param variants [Hash] the variants, described above
|
35
|
-
# @param add_langs [false, true] whether to supplant language tags
|
36
|
-
# @param all [false, true] whether to return a sorted list or not
|
37
|
-
# @param cmp [Proc] a secondary comparison of variants as a tiebreaker
|
31
|
+
# @return [Hash] the parsed `Accept*` headers
|
38
32
|
#
|
39
|
-
def
|
33
|
+
def parse_headers request, add_langs: false
|
40
34
|
# pull accept headers
|
41
35
|
request = request.env if request.respond_to? :env
|
36
|
+
|
37
|
+
# no-op if this is already parsed
|
38
|
+
return request if request.is_a? Hash and
|
39
|
+
request.all? { |k, v| k.is_a? Symbol and v.is_a? Hash }
|
40
|
+
|
42
41
|
# this will ensure that the keys will match irrespective of
|
43
42
|
# whether it's passed in as actual http headers or a cgi-like env
|
44
43
|
request = request.transform_keys do |k|
|
@@ -67,7 +66,7 @@ module HTTP::Negotiate
|
|
67
66
|
params = params.map do |p|
|
68
67
|
k, v = p.split(/=+/, 2)
|
69
68
|
k = k.downcase.to_sym
|
70
|
-
v = v.to_f if v and k == :q
|
69
|
+
v = v.to_f if v and k == :q
|
71
70
|
[k, v]
|
72
71
|
end.to_h
|
73
72
|
if params[:q]
|
@@ -100,6 +99,35 @@ module HTTP::Negotiate
|
|
100
99
|
end
|
101
100
|
end
|
102
101
|
|
102
|
+
accept
|
103
|
+
end
|
104
|
+
|
105
|
+
# The variant mapping takes the following form:
|
106
|
+
# { variant => [weight, type, encoding, charset, language, size] }
|
107
|
+
#
|
108
|
+
# (Alternatively this array can be a hash with the same keys as symbols.)
|
109
|
+
#
|
110
|
+
# * the variant can be anything, including the actual variant
|
111
|
+
# * the weight is a number between 0 and 1 denoting the initial
|
112
|
+
# preference for the variant
|
113
|
+
# * type, encoding, charset, language are all strings containing
|
114
|
+
# their respective standardized tokens (note "encoding" is like
|
115
|
+
# `gzip`, not like `utf-8`: that's "charset")
|
116
|
+
# * size is the number of bytes, an integer
|
117
|
+
#
|
118
|
+
# Returns either the winning variant or all variants if requested,
|
119
|
+
# sorted by the algorithm, or nil or the empty array if none are
|
120
|
+
# selected.
|
121
|
+
#
|
122
|
+
# @param request [Hash,Rack::Request,#env] Anything roughly a hash of headers
|
123
|
+
# @param variants [Hash] the variants, described above
|
124
|
+
# @param add_langs [false, true] whether to supplement language tags
|
125
|
+
# @param all [false, true] whether to return a sorted list or not
|
126
|
+
# @param cmp [Proc] a secondary comparison of variants as a tiebreaker
|
127
|
+
#
|
128
|
+
def negotiate request, variants, add_langs: false, all: false, cmp: nil
|
129
|
+
accept = parse_headers request, add_langs: add_langs
|
130
|
+
|
103
131
|
# convert variants to array
|
104
132
|
variants = variants.transform_values do |v|
|
105
133
|
v.is_a?(Hash) ? v.values_at(*KEYS) : v
|
@@ -145,24 +173,30 @@ module HTTP::Negotiate
|
|
145
173
|
|
146
174
|
# calculate the language quality
|
147
175
|
ql = 1
|
148
|
-
if accept[:language]
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
176
|
+
if accept[:language]
|
177
|
+
if language
|
178
|
+
ql = 0.001 # initial value is very low but not zero
|
179
|
+
lang = language.split(/-+/)
|
180
|
+
(0..lang.length).to_a.reverse.each do |i|
|
181
|
+
# apparently there is no wildcard for accept-language? no
|
182
|
+
# wait there is: rfc4647 $2.1 via rfc7231 $5.3.5
|
183
|
+
test = i > 0 ? lang.slice(0, i).join(?-) : ?*
|
184
|
+
if accept[:language][test]
|
185
|
+
al = accept[:language][test][:q]
|
186
|
+
# *;q=0 will override
|
187
|
+
if al == 0 and test != ?*
|
188
|
+
ql = 0
|
189
|
+
break
|
190
|
+
elsif al > ql
|
191
|
+
ql = al
|
192
|
+
end
|
160
193
|
end
|
161
194
|
end
|
195
|
+
elsif any_lang
|
196
|
+
# XXX not sure if language-less variants in the same pool
|
197
|
+
# with language-y ones
|
198
|
+
ql = 0.5
|
162
199
|
end
|
163
|
-
# apparently there is no wildcard for accept-language?
|
164
|
-
elsif accept[:language] and any_lang
|
165
|
-
ql = 0.5
|
166
200
|
end
|
167
201
|
|
168
202
|
# calculate the type quality
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http-negotiate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dorian Taylor
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.12'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
54
|
+
version: '3.12'
|
55
55
|
description:
|
56
56
|
email:
|
57
57
|
- code@doriantaylor.com
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- ".gitignore"
|
63
63
|
- ".rspec"
|
64
64
|
- ".travis.yml"
|
65
|
+
- ".yardopts"
|
65
66
|
- Gemfile
|
66
67
|
- LICENSE
|
67
68
|
- README.md
|
@@ -93,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
94
|
- !ruby/object:Gem::Version
|
94
95
|
version: '0'
|
95
96
|
requirements: []
|
96
|
-
rubygems_version: 3.
|
97
|
+
rubygems_version: 3.3.15
|
97
98
|
signing_key:
|
98
99
|
specification_version: 4
|
99
100
|
summary: An implementation of Gisle Aas's HTTP::Negotiate
|