http-negotiate 0.1.1 → 0.1.2

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: 37db2775817222cbcb2d1d27845d37011cfec405d7b8ddc9f0030383bc53264c
4
- data.tar.gz: 84e031f85bc9d04b8f1ed52213a0c681e5be4bb638e0ab13881f5320a0ad511a
3
+ metadata.gz: 97e8bcc59dec991c82e9e253b34ab3643ee7b62441b2d890c1988bcd2bd6a941
4
+ data.tar.gz: 66a3825c19b6ab786a4b1fdca2cd5fff90d03b91d72aea495576f2e3312c2bb1
5
5
  SHA512:
6
- metadata.gz: bde399e1e18835553bd15b72c9062c98d6560b7ae8e705739f4e4ea3fc96caa70b2db000b93897c5470a71f9f8cdc0a7674fc1afb2952d841a43c652c5a447fe
7
- data.tar.gz: 6575f6321b5beac495967b5e42fca6e2c238a4e7171588ef3e653efa925397cf8a8e2d3563ee7ba395e5cb012d4bd12edf06277b0468dc4189c90398a2d9939a
6
+ metadata.gz: 89807147d59bfeadcfa20e4228bbd6de119c2bcadcfcf76c204516e20a47c049c8c0a7d736e05265f5f737d10ce8b1c4a49ee7da4719a0c30abe7e62dba57c2c
7
+ data.tar.gz: 8f83584309e4a1fb37b46c53b3618bba9a470030414e20d30c8f96bbf09deecc003674fd265262193ea4fecf3053de20927f35fd676a547c46586941e77e8381
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in http-negotiate.gemspec
4
4
  gemspec
5
5
 
6
- gem "rake", "~> 13.0"
7
- gem "rspec", "~> 3.0"
6
+ #gem "rake", "~> 13.0"
7
+ #gem "rspec", "~> 3.0"
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
30
30
 
31
31
  # dev/test dependencies
32
- spec.add_development_dependency 'bundler', '~> 2.1'
32
+ spec.add_development_dependency 'bundler', '~> 2.2'
33
33
  spec.add_development_dependency 'rake', '~> 13.0'
34
- spec.add_development_dependency 'rspec', '~> 3.9'
34
+ spec.add_development_dependency 'rspec', '~> 3.10'
35
35
  end
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  module Negotiate
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end
5
5
  end
@@ -32,10 +32,11 @@ module HTTP::Negotiate
32
32
  #
33
33
  # @param request [Hash,Rack::Request,#env] Anything roughly a hash of headers
34
34
  # @param variants [Hash] the variants, described above
35
+ # @param add_langs [false, true] whether to supplant language tags
35
36
  # @param all [false, true] whether to return a sorted list or not
36
37
  # @param cmp [Proc] a secondary comparison of variants as a tiebreaker
37
38
  #
38
- def negotiate request, variants, all: false, cmp: nil
39
+ def negotiate request, variants, add_langs: false, all: false, cmp: nil
39
40
  # pull accept headers
40
41
  request = request.env if request.respond_to? :env
41
42
  # this will ensure that the keys will match irrespective of
@@ -56,6 +57,11 @@ module HTTP::Negotiate
56
57
  # but we don't care (although interestingly according to rfc7231,
57
58
  # accept-language only affords q= and not arbitrary parameters)
58
59
  hdr = hdr.dup.gsub(/\s+/, '')
60
+
61
+ # don't add the test group if it's an empty string, because
62
+ # postel's law is a thing
63
+ next if hdr.empty?
64
+
59
65
  accept[k] = hdr.split(/,+/).map do |c|
60
66
  val, *params = c.split(/;+/)
61
67
  params = params.map do |p|
@@ -77,6 +83,23 @@ module HTTP::Negotiate
77
83
  end
78
84
  end
79
85
 
86
+ # sneakily supplant shorter language tags at 99% q
87
+ if accept[:language]
88
+ langs = accept[:language]
89
+ langs.transform_keys! { |k| k.tr(?_, ?-).tr_s(?-, ?-).downcase }
90
+ if add_langs
91
+ langs.keys.select { |k| k.include? ?- }.each do |k|
92
+ # a tag with q=0 has to be explicitly set in the header
93
+ next if (q = langs[k][:q]) == 0
94
+ lang = k.split ?-
95
+ (1..lang.length).to_a.reverse.each do |i|
96
+ # each shorter language tag will have a slightly lower score
97
+ langs[lang.slice(0, i).join ?-] ||= { q: q *= 0.999 }
98
+ end
99
+ end
100
+ end
101
+ end
102
+
80
103
  # convert variants to array
81
104
  variants = variants.transform_values do |v|
82
105
  v.is_a?(Hash) ? v.values_at(*KEYS) : v
@@ -162,37 +185,32 @@ module HTTP::Negotiate
162
185
  # warn maj.inspect, min.inspect
163
186
 
164
187
  # XXX match params at some point
165
- if at[maj]
166
- if at[maj][min]
167
- qt = at[maj][min][:q]
168
- elsif at[maj][?*]
169
- qt = at[maj][?*][:q]
170
- else
171
- qt = 0.1
172
- end
173
- elsif at[?*]
174
- # ???
175
- qt = at[?*].fetch(?*, { q: 0.1 })[:q]
176
- else
177
- # ???
178
- qt = 0.1
179
- end
188
+ qt = if at.fetch(maj, {})[min]
189
+ at[maj][min][:q]
190
+ elsif at.fetch(maj, {})[?*]
191
+ at[maj][?*][:q]
192
+ elsif at.fetch(?*, {})[?*]
193
+ at[?*][?*][:q]
194
+ else
195
+ 0.1
196
+ end
180
197
 
181
198
  end
182
199
 
183
- scores[var] = qs * qe * qc * ql * qt
200
+ scores[var] = [qs * qe * qc * ql * qt, size]
184
201
  end
185
202
 
186
203
  # XXX do something smarter here for secondary comparison
187
204
  cmp ||= -> a, b { 0 }
188
205
 
189
206
  chosen = scores.sort do |a, b|
190
- c = b.last <=> a.last
191
- c == 0 ? cmp.call(a.first, b.first) : c
207
+ c = b.last.first <=> a.last.first # first compare scores
208
+ c = cmp.call(a.first, b.first) if c == 0 # then secondary cmp
209
+ c == 0 ? a.last.last <=> b.last.last : c # then finally by size
192
210
  end.map(&:first)
211
+
193
212
  all ? chosen : chosen.first
194
213
  end
195
214
 
196
215
  extend self
197
216
  end
198
- 3
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-negotiate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Taylor
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.1'
19
+ version: '2.2'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.1'
26
+ version: '2.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.9'
47
+ version: '3.10'
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.9'
54
+ version: '3.10'
55
55
  description:
56
56
  email:
57
57
  - code@doriantaylor.com