http-negotiate 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97e8bcc59dec991c82e9e253b34ab3643ee7b62441b2d890c1988bcd2bd6a941
4
- data.tar.gz: 66a3825c19b6ab786a4b1fdca2cd5fff90d03b91d72aea495576f2e3312c2bb1
3
+ metadata.gz: 6c40df3f0c699e99b0f45c3af71e19e5461878bddecf1a8a28a4125965cc05c9
4
+ data.tar.gz: 58dfdd11e0a9b119f5e84bdb24e8d2d28145e91d7a8fa3d5d3067572d1c2980e
5
5
  SHA512:
6
- metadata.gz: 89807147d59bfeadcfa20e4228bbd6de119c2bcadcfcf76c204516e20a47c049c8c0a7d736e05265f5f737d10ce8b1c4a49ee7da4719a0c30abe7e62dba57c2c
7
- data.tar.gz: 8f83584309e4a1fb37b46c53b3618bba9a470030414e20d30c8f96bbf09deecc003674fd265262193ea4fecf3053de20927f35fd676a547c46586941e77e8381
6
+ metadata.gz: 0610a598b694dfa3a147257e160dfbfafcde951715ff7329f489b22e097490e2999f84a8401ef6019183f30fbbdbe01c31c4daf7dd9abcab34402add0a1f96bc
7
+ data.tar.gz: b3a19ba49afe90cd32aba42046ec57af147bb1a12f7087102fed03e5520c30cc33fecc41785a226cf7a5680298adcb59ea2b14a9bcd6950db3b2148109a070be
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --markup=markdown
2
+ --no-private
3
+ - README.md
4
+ - LICENSE
5
+ - CHANGELOG.md
@@ -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.10'
34
+ spec.add_development_dependency 'rspec', '~> 3.12'
35
35
  end
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  module Negotiate
3
- VERSION = '0.1.2'
3
+ VERSION = '0.2.0'
4
4
  end
5
5
  end
@@ -13,32 +13,31 @@ module HTTP::Negotiate
13
13
 
14
14
  public
15
15
 
16
- # The variant mapping takes the following form:
17
- # { variant => [weight, type, encoding, charset, language, size] }
18
- #
19
- # (Alternatively this array can be a hash with the same keys as symbols.)
20
- #
21
- # * the variant can be anything, including the actual variant
22
- # * the weight is a number between 0 and 1 denoting the initial
23
- # preference for the variant
24
- # * type, encoding, charset, language are all strings containing
25
- # their respective standardized tokens (note "encoding" is like
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
- # Returns either the winning variant or all variants if requested,
30
- # sorted by the algorithm, or nil or the empty array if none are
31
- # selected.
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
- # @param request [Hash,Rack::Request,#env] Anything roughly a hash of headers
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 negotiate request, variants, add_langs: false, all: false, cmp: nil
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] and language
149
- ql = 0.001 # initial value is very low but not zero
150
- lang = language.split(/-+/)
151
- (1..lang.length).to_a.reverse.each do |i|
152
- test = lang.slice(0, i).join ?-
153
- if accept[:language][test]
154
- al = accept[:language][test][:q]
155
- if al == 0
156
- ql = 0
157
- break
158
- elsif al > ql
159
- ql = al
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.1.2
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: 2021-11-08 00:00:00.000000000 Z
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.10'
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.10'
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.2.22
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