acceptable 0.2.2 → 0.2.3
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.
- data/README.rdoc +58 -25
- data/lib/rack/acceptable.rb +3 -0
- data/lib/rack/acceptable/language_tag.rb +31 -22
- data/lib/rack/acceptable/mixin/charsets.rb +55 -0
- data/lib/rack/acceptable/mixin/encodings.rb +30 -0
- data/lib/rack/acceptable/mixin/headers.rb +6 -76
- data/lib/rack/acceptable/mixin/languages.rb +46 -0
- data/lib/rack/acceptable/mixin/media.rb +18 -6
- data/lib/rack/acceptable/request.rb +5 -15
- data/lib/rack/acceptable/utils.rb +3 -2
- data/lib/rack/acceptable/version.rb +1 -1
- metadata +15 -5
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
== DESCRIPTION:
|
2
2
|
|
3
3
|
Provides definitive support for Accept-* headers, strictly compliant with RFC 2616.
|
4
4
|
Includes negotiation algorithms for Media-Types, Charsets and Content-Codings.
|
@@ -14,40 +14,73 @@ Also realizes perfectionistic LanguageTags support with basic/extended filtering
|
|
14
14
|
|
15
15
|
== EXAMPLES:
|
16
16
|
|
17
|
-
===
|
17
|
+
=== Helpers:
|
18
18
|
|
19
|
-
env = Rack::MockRequest.env_for('/',
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
env = Rack::MockRequest.env_for('/',
|
20
|
+
'HTTP_ACCEPT' => 'text/*;q=0.8,text/x-json;q=0.8,text/html;p=whatever,image/png;q=0.2',
|
21
|
+
'HTTP_ACCEPT_LANGUAGE' => 'de-de,sl-nedis',
|
22
|
+
'HTTP_ACCEPT_CHARSET' => 'utf-8;q=0.9,iso-8859-5;q=0.8'
|
23
|
+
)
|
24
24
|
|
25
|
-
|
26
|
-
request = Request.new(env)
|
27
|
-
p request.preferred_media_from('text/css','text/html') #=> "text/css"
|
28
|
-
p request.preferred_media_from('text/x-json','text/html;p=whatever') #=> "text/html;p=whatever"
|
29
|
-
p request.preferred_media_from('text/x-json','text/html;p=Whatever') #=> "text/x-json" #parameter values are case-sensitive.
|
25
|
+
request = Rack::Acceptable::Request.new(env)
|
30
26
|
|
31
|
-
|
27
|
+
==== Media:
|
28
|
+
|
29
|
+
request.accept_media?('text/css') #=> true
|
30
|
+
request.accept_media?('text/plain') #=> true
|
31
|
+
request.accept_media?('image/jpeg') #=> false
|
32
|
+
request.accept_media?('image/png') #=> true
|
33
|
+
request.accept_media?('video/quicktime') #=> false
|
34
|
+
|
35
|
+
request.preferred_media_from('text/css','text/html') #=> "text/css"
|
36
|
+
request.preferred_media_from('text/x-json','text/html;p=whatever') #=> "text/html;p=whatever"
|
37
|
+
request.preferred_media_from('text/x-json','text/html;p=Whatever') #=> "text/x-json" #parameter values are case-sensitive.
|
38
|
+
|
39
|
+
==== Languages:
|
40
|
+
|
41
|
+
request.accept_language?("de-de") #=> true
|
42
|
+
request.accept_language?("de-DE") #=> true
|
43
|
+
request.accept_language?("de-Latn-de") #=> true
|
44
|
+
request.accept_language?("de-Latf-DE") #=> true
|
45
|
+
request.accept_language?("de-DE-x-goethe") #=> true
|
46
|
+
request.accept_language?("de-Latn-DE-1996") #=> true
|
47
|
+
request.accept_language?("de-Deva-DE") #=> true
|
48
|
+
|
49
|
+
request.accept_language?("de") #=> false
|
50
|
+
request.accept_language?("de-x-DE") #=> false
|
51
|
+
request.accept_language?("de-Deva") #=> false
|
52
|
+
|
53
|
+
request.accept_language?("sl-nedis") #=> true
|
54
|
+
request.accept_language?("sl-Latn-nedis") #=> true
|
55
|
+
request.accept_language?("sl-rozaj") #=> false
|
56
|
+
|
57
|
+
==== Charsets:
|
58
|
+
|
59
|
+
request.accept_charset?("utf-8") #=> # true
|
60
|
+
request.accept_charset?("iso-8859-1") #=> # true
|
61
|
+
|
62
|
+
request.preferred_charset_from("utf-8","iso-8859-5") #=> # "utf-8"
|
63
|
+
request.preferred_charset_from("utf-8","iso-8859-1") #=> # "iso-8859-1"
|
64
|
+
|
65
|
+
=== LanguageTags:
|
32
66
|
|
33
67
|
langtag = Rack::Acceptable::LanguageTag.parse('SL-LATN-ROZAJ')
|
34
68
|
|
35
|
-
|
36
|
-
|
69
|
+
langtag.variants #=> ["rozaj"]
|
70
|
+
langtag.script #=> "Latn"
|
37
71
|
|
38
72
|
# basic filtering (RFC 4647)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
73
|
+
langtag.has_prefix?('sl-Latn') #=> true
|
74
|
+
langtag.matched_by_basic_range?('sl-Latn') #=> true
|
75
|
+
langtag.has_prefix?('sl-Latn-ro') #=> false
|
76
|
+
langtag.has_prefix?('sl') #=> true
|
43
77
|
|
44
78
|
# extended filtering (RFC 4647)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
79
|
+
langtag.matched_by_extended_range?('*') #=> true
|
80
|
+
langtag.matched_by_extended_range?('sl-*') #=> true
|
81
|
+
langtag.matched_by_extended_range?('*-Latn') #=> true
|
82
|
+
langtag.matched_by_extended_range?('sl-rozaj') #=> true
|
83
|
+
langtag.matched_by_extended_range?('sl-nedis') #=> false
|
51
84
|
|
52
85
|
== INSTALLATION:
|
53
86
|
|
data/lib/rack/acceptable.rb
CHANGED
@@ -13,6 +13,9 @@ module Rack #:nodoc:
|
|
13
13
|
|
14
14
|
# request and mixins
|
15
15
|
autoload :Headers , 'rack/acceptable/mixin/headers'
|
16
|
+
autoload :Encodings , 'rack/acceptable/mixin/encodings'
|
17
|
+
autoload :Charsets , 'rack/acceptable/mixin/charsets'
|
18
|
+
autoload :Languages , 'rack/acceptable/mixin/languages'
|
16
19
|
autoload :Media , 'rack/acceptable/mixin/media'
|
17
20
|
autoload :Request , 'rack/acceptable/request'
|
18
21
|
|
@@ -39,6 +39,7 @@ module Rack #:nodoc:
|
|
39
39
|
}.freeze
|
40
40
|
|
41
41
|
attr_accessor :primary, :extlang, :script, :region, :variants, :extensions, :privateuse
|
42
|
+
attr_reader :length
|
42
43
|
|
43
44
|
#--
|
44
45
|
# RFC 5646, sec. 2.2.2:
|
@@ -51,7 +52,7 @@ module Rack #:nodoc:
|
|
51
52
|
# always remain, invalid.
|
52
53
|
#++
|
53
54
|
|
54
|
-
language = '([a-z]{2,8}|[a-z]{2,3}(?:-[a-z]{3})
|
55
|
+
language = '([a-z]{2,8}|[a-z]{2,3}(?:-[a-z]{3}){0,3})'
|
55
56
|
script = '(?:-([a-z]{4}))?'
|
56
57
|
region = '(?:-([a-z]{2}|\d{3}))?'
|
57
58
|
variants = '(?:-[a-z\d]{5,8}|-\d[a-z\d]{3})*'
|
@@ -66,14 +67,14 @@ module Rack #:nodoc:
|
|
66
67
|
|
67
68
|
class << self
|
68
69
|
|
69
|
-
# Checks if the +String+ passed
|
70
|
+
# Checks if the +String+ passed represents a 'privateuse' Language-Tag.
|
70
71
|
# Works case-insensitively.
|
71
72
|
#
|
72
73
|
def privateuse?(tag)
|
73
74
|
PRIVATEUSE_REGEX === tag
|
74
75
|
end
|
75
76
|
|
76
|
-
# Checks if the +String+ passed represents a '
|
77
|
+
# Checks if the +String+ passed represents a 'grandfathered' Language-Tag.
|
77
78
|
# Works case-insensitively.
|
78
79
|
#
|
79
80
|
def grandfathered?(tag)
|
@@ -81,13 +82,13 @@ module Rack #:nodoc:
|
|
81
82
|
end
|
82
83
|
|
83
84
|
# ==== Parameters
|
84
|
-
# langtag<String>:: The
|
85
|
+
# langtag<String>:: The LangTag snippet.
|
85
86
|
#
|
86
87
|
# ==== Returns
|
87
88
|
# Array or nil::
|
88
|
-
# It returns +nil+, when the
|
89
|
+
# It returns +nil+, when the snipped passed:
|
89
90
|
# * does not conform the Language-Tag ABNF (malformed)
|
90
|
-
# * grandfathered
|
91
|
+
# * represents a 'grandfathered' Language-Tag
|
91
92
|
# * starts with 'x' singleton ('privateuse').
|
92
93
|
#
|
93
94
|
# Otherwise you'll get an +Array+ with:
|
@@ -112,7 +113,7 @@ module Rack #:nodoc:
|
|
112
113
|
region = $3
|
113
114
|
variants = $4.split(Utils::HYPHEN_SPLITTER)[1..-1]
|
114
115
|
|
115
|
-
primary, extlang = primary.split(Utils::HYPHEN_SPLITTER) if primary.include?(Const::HYPHEN)
|
116
|
+
primary, *extlang = primary.split(Utils::HYPHEN_SPLITTER) if primary.include?(Const::HYPHEN)
|
116
117
|
script.capitalize! if script
|
117
118
|
region.upcase! if region
|
118
119
|
|
@@ -130,17 +131,10 @@ module Rack #:nodoc:
|
|
130
131
|
# Checks if self has a variant passed.
|
131
132
|
# Works case-insensitively.
|
132
133
|
#
|
133
|
-
# ==== Notes
|
134
|
-
# *Destructively* downcases current set of variants, if necessary.
|
135
|
-
# Just note, that variants are case-insensitive, and 'convenient' form
|
136
|
-
# of the Languge-Tag assumes they're in 'lowercase' notation.
|
137
|
-
#
|
138
134
|
def has_variant?(variant)
|
139
135
|
return false unless @variants
|
140
|
-
|
141
|
-
|
142
|
-
@variants.include?(variant.downcase)
|
143
|
-
end
|
136
|
+
v = variant.downcase
|
137
|
+
@variants.any? { |var| v == var || v == var.downcase }
|
144
138
|
end
|
145
139
|
|
146
140
|
# Checks if self has a singleton passed.
|
@@ -174,6 +168,20 @@ module Rack #:nodoc:
|
|
174
168
|
|
175
169
|
attr_reader :tag # the most recent 'build' of tag
|
176
170
|
|
171
|
+
# Returns the number of subtags in self.
|
172
|
+
# Does *not* perform validation or recomposition.
|
173
|
+
#
|
174
|
+
def length
|
175
|
+
length = 1 #@primary
|
176
|
+
length += @extlang.length if @extlang
|
177
|
+
length += 1 if @script
|
178
|
+
length += 1 if @region
|
179
|
+
length += @variants.length if @variants
|
180
|
+
@extensions.each { |_,e| length += e.length+1 } if @extensions # length += @extenstions.to_a.flatten.length if @extensions
|
181
|
+
length += @privateuse.length+1 if @privateuse
|
182
|
+
length
|
183
|
+
end
|
184
|
+
|
177
185
|
def nicecased
|
178
186
|
recompose # we could not conveniently format malformed or invalid tags
|
179
187
|
@nicecased #.dup #uuuuugh
|
@@ -181,7 +189,7 @@ module Rack #:nodoc:
|
|
181
189
|
|
182
190
|
def to_a
|
183
191
|
ary = [@primary]
|
184
|
-
ary
|
192
|
+
ary.concat @extlang if @extlang
|
185
193
|
ary << @script if @script
|
186
194
|
ary << @region if @region
|
187
195
|
ary.concat @variants if @variants
|
@@ -218,7 +226,8 @@ module Rack #:nodoc:
|
|
218
226
|
# de-Deva ('Deva' not equal to 'DE')
|
219
227
|
#++
|
220
228
|
|
221
|
-
# Checks if the *extended* Language-Range
|
229
|
+
# Checks if the *extended* Language-Range (in the shortest notation)
|
230
|
+
# passed matches self.
|
222
231
|
def matched_by_extended_range?(range)
|
223
232
|
recompose
|
224
233
|
subtags = @composition.split(Const::HYPHEN)
|
@@ -324,16 +333,16 @@ module Rack #:nodoc:
|
|
324
333
|
|
325
334
|
# ==== Parameters
|
326
335
|
# thing<String, optional>::
|
327
|
-
# The
|
336
|
+
# The LangTag snippet
|
328
337
|
#
|
329
338
|
# ==== Returns
|
330
339
|
# +self+
|
331
340
|
#
|
332
341
|
# ==== Raises
|
333
342
|
# ArgumentError::
|
334
|
-
# The
|
343
|
+
# The snippet passed:
|
335
344
|
# * does not conform the Language-Tag ABNF (malformed)
|
336
|
-
# * grandfathered
|
345
|
+
# * represents a 'grandfathered' Language-Tag
|
337
346
|
# * starts with 'x' singleton ('privateuse').
|
338
347
|
# * contains duplicate variants
|
339
348
|
# * contains duplicate singletons
|
@@ -359,7 +368,7 @@ module Rack #:nodoc:
|
|
359
368
|
components = $'.split(Utils::HYPHEN_SPLITTER)
|
360
369
|
components.shift
|
361
370
|
|
362
|
-
@primary,
|
371
|
+
@primary, *@extlang = @primary.split(Utils::HYPHEN_SPLITTER) if @primary.include?(Const::HYPHEN)
|
363
372
|
|
364
373
|
@script.capitalize! if @script
|
365
374
|
@region.upcase! if @region
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rack/acceptable/utils'
|
2
|
+
|
3
|
+
module Rack #:nodoc:
|
4
|
+
module Acceptable #:nodoc:
|
5
|
+
module Charsets
|
6
|
+
|
7
|
+
# ==== Returns
|
8
|
+
# An Array with wildcards / *downcased* Charsets and
|
9
|
+
# associated quality factors (qvalues). Default qvalue is 1.0.
|
10
|
+
#
|
11
|
+
# ==== Raises
|
12
|
+
# ArgumentError::
|
13
|
+
# Syntax of the Accept-Charset request-header is bad.
|
14
|
+
# For example, one of Charsets is not a 'token',
|
15
|
+
# one of quality factors is malformed etc.
|
16
|
+
#
|
17
|
+
def acceptable_charsets
|
18
|
+
Utils.parse_header(
|
19
|
+
env[Const::ENV_HTTP_ACCEPT_CHARSET].to_s.downcase,
|
20
|
+
Utils::HTTP_ACCEPT_TOKEN_REGEX)
|
21
|
+
rescue
|
22
|
+
raise ArgumentError,
|
23
|
+
"Malformed Accept-Charset header: #{env[Const::ENV_HTTP_ACCEPT_CHARSET].inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Checks if the Charset (as a +String+) passed acceptable.
|
27
|
+
# Works case-insensitively.
|
28
|
+
#
|
29
|
+
def accept_charset?(chs)
|
30
|
+
chs = chs.downcase
|
31
|
+
return true if (accepts = acceptable_charsets).empty?
|
32
|
+
if ch = accepts.assoc(chs) || accepts.assoc(Const::WILDCARD)
|
33
|
+
ch.last > 0
|
34
|
+
else
|
35
|
+
chs == Const::ISO_8859_1
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
# Detects the best Charset.
|
42
|
+
# Works case-insensitively.
|
43
|
+
#
|
44
|
+
def negotiate_charset(*things)
|
45
|
+
things.map!{|t| t.downcase}
|
46
|
+
Utils.detect_best_charset(things, acceptable_charsets)
|
47
|
+
end
|
48
|
+
|
49
|
+
alias :preferred_charset_from :negotiate_charset
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# EOF
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rack/acceptable/utils'
|
2
|
+
|
3
|
+
module Rack #:nodoc:
|
4
|
+
module Acceptable #:nodoc:
|
5
|
+
module Encodings
|
6
|
+
|
7
|
+
# ==== Returns
|
8
|
+
# An Array with wildcards / *downcased* Content-Codings
|
9
|
+
# and associated quality factors (qvalues). Default qvalue is 1.0.
|
10
|
+
#
|
11
|
+
# ==== Raises
|
12
|
+
# ArgumentError::
|
13
|
+
# Syntax of the Accept-Encoding request-header is bad.
|
14
|
+
# For example, one of Content-Codings is not a 'token',
|
15
|
+
# one of quality factors is malformed etc.
|
16
|
+
#
|
17
|
+
def acceptable_encodings
|
18
|
+
Utils.parse_header(
|
19
|
+
env[Const::ENV_HTTP_ACCEPT_ENCODING].to_s.downcase,
|
20
|
+
Utils::HTTP_ACCEPT_TOKEN_REGEX)
|
21
|
+
rescue
|
22
|
+
raise ArgumentError,
|
23
|
+
"Malformed Accept-Encoding header: #{env[Const::ENV_HTTP_ACCEPT_ENCODING].inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# EOF
|
@@ -1,84 +1,14 @@
|
|
1
|
-
require 'rack/acceptable/
|
1
|
+
require 'rack/acceptable/mixin/charsets'
|
2
|
+
require 'rack/acceptable/mixin/encodings'
|
3
|
+
require 'rack/acceptable/mixin/languages'
|
4
|
+
require 'rack/acceptable/mixin/media'
|
2
5
|
|
3
6
|
module Rack #:nodoc:
|
4
7
|
module Acceptable #:nodoc:
|
5
8
|
module Headers
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
# and associated quality factors (qvalues). Default qvalue is 1.0.
|
10
|
-
#
|
11
|
-
# ==== Raises
|
12
|
-
# ArgumentError::
|
13
|
-
# Syntax of the Accept-Encoding request-header is bad.
|
14
|
-
# For example, one of Content-Codings is not a 'token',
|
15
|
-
# one of quality factors is malformed etc.
|
16
|
-
#
|
17
|
-
def acceptable_encodings
|
18
|
-
Utils.parse_header(
|
19
|
-
env[Const::ENV_HTTP_ACCEPT_ENCODING].to_s.downcase,
|
20
|
-
Utils::HTTP_ACCEPT_TOKEN_REGEX)
|
21
|
-
rescue
|
22
|
-
raise ArgumentError,
|
23
|
-
"Malformed Accept-Encoding header: #{env[Const::ENV_HTTP_ACCEPT_ENCODING].inspect}"
|
24
|
-
end
|
25
|
-
|
26
|
-
# ==== Returns
|
27
|
-
# An Array with wildcards / *downcased* Charsets and
|
28
|
-
# associated quality factors (qvalues). Default qvalue is 1.0.
|
29
|
-
#
|
30
|
-
# ==== Raises
|
31
|
-
# ArgumentError::
|
32
|
-
# Syntax of the Accept-Charset request-header is bad.
|
33
|
-
# For example, one of Charsets is not a 'token',
|
34
|
-
# one of quality factors is malformed etc.
|
35
|
-
#
|
36
|
-
def acceptable_charsets
|
37
|
-
Utils.parse_header(
|
38
|
-
env[Const::ENV_HTTP_ACCEPT_CHARSET].to_s.downcase,
|
39
|
-
Utils::HTTP_ACCEPT_TOKEN_REGEX)
|
40
|
-
rescue
|
41
|
-
raise ArgumentError,
|
42
|
-
"Malformed Accept-Charset header: #{env[Const::ENV_HTTP_ACCEPT_CHARSET].inspect}"
|
43
|
-
end
|
44
|
-
|
45
|
-
# ==== Returns
|
46
|
-
# An Array with wildcards / Language-Tags (as +Strings+)
|
47
|
-
# and associated quality factors (qvalues). Default qvalue is 1.0.
|
48
|
-
#
|
49
|
-
# ==== Raises
|
50
|
-
# ArgumentError::
|
51
|
-
# Syntax of the Accept-Language request-header is bad.
|
52
|
-
# For example, one of Language-Ranges is not in a RFC 'Language-Range'
|
53
|
-
# pattern, one of quality factors is malformed etc.
|
54
|
-
#
|
55
|
-
# ==== Notes
|
56
|
-
# * It uses {Extended Language-Range pattern}[http://tools.ietf.org/html/rfc4647#section-2.2].
|
57
|
-
# * It does *not* perform 'convenient transformations' (downcasing of primary tags etc).
|
58
|
-
# In other words, it parses Accept-Language header in unpretentious manner.
|
59
|
-
#
|
60
|
-
def acceptable_language_ranges
|
61
|
-
Utils.parse_header(
|
62
|
-
env[Const::ENV_HTTP_ACCEPT_LANGUAGE].to_s,
|
63
|
-
Utils::HTTP_ACCEPT_LANGUAGE_REGEX)
|
64
|
-
rescue
|
65
|
-
raise ArgumentError,
|
66
|
-
"Malformed Accept-Language header: #{env[Const::ENV_HTTP_ACCEPT_LANGUAGE].inspect}"
|
67
|
-
end
|
68
|
-
|
69
|
-
# ==== Returns
|
70
|
-
# An Array with Media-Ranges (as +Strings+) / wildcards and
|
71
|
-
# associated qvalues. Default qvalue is 1.0.
|
72
|
-
#
|
73
|
-
# ==== Raises
|
74
|
-
# ArgumentError::
|
75
|
-
# There's a malformed qvalue in header.
|
76
|
-
#
|
77
|
-
def acceptable_media_ranges
|
78
|
-
Utils.extract_qvalues(env[Const::ENV_HTTP_ACCEPT].to_s)
|
79
|
-
rescue
|
80
|
-
raise ArgumentError,
|
81
|
-
"Malformed Accept header: #{env[Const::ENV_HTTP_ACCEPT].inspect}"
|
10
|
+
def self.included(mod)
|
11
|
+
mod.send :include, Charsets, Encodings, Languages, Media
|
82
12
|
end
|
83
13
|
|
84
14
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rack/acceptable/language_tag'
|
2
|
+
|
3
|
+
module Rack #:nodoc:
|
4
|
+
module Acceptable #:nodoc:
|
5
|
+
module Languages
|
6
|
+
|
7
|
+
# ==== Returns
|
8
|
+
# An Array with wildcards / Language-Tags (as +Strings+)
|
9
|
+
# and associated quality factors (qvalues). Default qvalue is 1.0.
|
10
|
+
#
|
11
|
+
# ==== Raises
|
12
|
+
# ArgumentError::
|
13
|
+
# Syntax of the Accept-Language request-header is bad.
|
14
|
+
# For example, one of Language-Ranges is not in a RFC 'Language-Range'
|
15
|
+
# pattern, one of quality factors is malformed etc.
|
16
|
+
#
|
17
|
+
# ==== Notes
|
18
|
+
# * It uses {Extended Language-Range pattern}[http://tools.ietf.org/html/rfc4647#section-2.2].
|
19
|
+
# * It does *not* perform 'convenient transformations' (downcasing of primary tags etc).
|
20
|
+
# In other words, it parses Accept-Language header in unpretentious manner.
|
21
|
+
#
|
22
|
+
def acceptable_language_ranges
|
23
|
+
Utils.parse_header(
|
24
|
+
env[Const::ENV_HTTP_ACCEPT_LANGUAGE].to_s,
|
25
|
+
Utils::HTTP_ACCEPT_LANGUAGE_REGEX)
|
26
|
+
rescue
|
27
|
+
raise ArgumentError,
|
28
|
+
"Malformed Accept-Language header: #{env[Const::ENV_HTTP_ACCEPT_LANGUAGE].inspect}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Checks if the Language-Tag (as a +String+ or
|
32
|
+
# +Rack::Acceptable::LanguageTag+) passed acceptable.
|
33
|
+
# Works case-insensitively.
|
34
|
+
#
|
35
|
+
def accept_language?(tag)
|
36
|
+
langtag = LanguageTag.parse(tag)
|
37
|
+
acceptable_language_ranges.any? { |l,q| q > 0 && langtag.matched_by_extended_range?(l) }
|
38
|
+
rescue
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# EOF
|
@@ -4,6 +4,21 @@ module Rack #:nodoc:
|
|
4
4
|
module Acceptable #:nodoc:
|
5
5
|
module Media
|
6
6
|
|
7
|
+
# ==== Returns
|
8
|
+
# An Array with Media-Ranges (as +Strings+) / wildcards and
|
9
|
+
# associated qvalues. Default qvalue is 1.0.
|
10
|
+
#
|
11
|
+
# ==== Raises
|
12
|
+
# ArgumentError::
|
13
|
+
# There's a malformed qvalue in header.
|
14
|
+
#
|
15
|
+
def acceptable_media_ranges
|
16
|
+
Utils.extract_qvalues(env[Const::ENV_HTTP_ACCEPT].to_s)
|
17
|
+
rescue
|
18
|
+
raise ArgumentError,
|
19
|
+
"Malformed Accept header: #{env[Const::ENV_HTTP_ACCEPT].inspect}"
|
20
|
+
end
|
21
|
+
|
7
22
|
# ==== Returns
|
8
23
|
# An Array with *completely* parsed MIME-Types (incl. qvalues
|
9
24
|
# and accept-extensions; see Rack::Acceptable::MIMETypes).
|
@@ -17,16 +32,13 @@ module Rack #:nodoc:
|
|
17
32
|
# or, at last, one of MIME-Types has malformed qvalue.
|
18
33
|
#
|
19
34
|
def acceptable_media
|
20
|
-
|
21
|
-
|
22
|
-
header.split(Utils::COMMA_SPLITTER).map! { |entry| MIMETypes.parse_mime_type(entry) }
|
23
|
-
end
|
35
|
+
header = env[Const::ENV_HTTP_ACCEPT].to_s
|
36
|
+
header.split(Utils::COMMA_SPLITTER).map! { |entry| MIMETypes.parse_mime_type(entry) }
|
24
37
|
end
|
25
38
|
|
26
39
|
# Checks if the MIME-Type passed acceptable.
|
27
40
|
def accept_media?(thing)
|
28
|
-
|
29
|
-
qvalue > 0
|
41
|
+
MIMETypes.weigh_mime_type(thing, acceptable_media).first > 0
|
30
42
|
rescue
|
31
43
|
false
|
32
44
|
end
|
@@ -1,28 +1,18 @@
|
|
1
1
|
require 'rack/request'
|
2
2
|
require 'rack/acceptable/mixin/headers'
|
3
|
-
require 'rack/acceptable/mixin/media'
|
4
3
|
|
5
4
|
module Rack #:nodoc:
|
6
5
|
module Acceptable #:nodoc:
|
7
6
|
class Request < Rack::Request
|
7
|
+
|
8
8
|
include Rack::Acceptable::Headers
|
9
|
-
include Rack::Acceptable::Media
|
10
9
|
|
11
|
-
def
|
12
|
-
@
|
10
|
+
def acceptable_media
|
11
|
+
@_acceptable_media ||= super
|
13
12
|
end
|
14
13
|
|
15
|
-
def
|
16
|
-
|
17
|
-
accepts = acceptable_charsets
|
18
|
-
return true if accepts.empty?
|
19
|
-
if ch = accepts.assoc(chs) || accepts.assoc(Const::WILDCARD)
|
20
|
-
ch.last > 0
|
21
|
-
else
|
22
|
-
chs == Const::ISO_8859_1
|
23
|
-
end
|
24
|
-
rescue
|
25
|
-
false
|
14
|
+
def acceptable_charsets
|
15
|
+
@_acceptable_charsets ||= super
|
26
16
|
end
|
27
17
|
|
28
18
|
def accept_content?(content_type)
|
@@ -23,8 +23,8 @@ module Rack #:nodoc:
|
|
23
23
|
if RUBY_VERSION < '1.9.1'
|
24
24
|
|
25
25
|
PAIR_SPLITTER = /\=/.freeze
|
26
|
-
HYPHEN_SPLITTER =
|
27
|
-
COMMA_SPLITTER =
|
26
|
+
HYPHEN_SPLITTER = /-/.freeze
|
27
|
+
COMMA_SPLITTER = /,/.freeze
|
28
28
|
SEMICOLON_SPLITTER = /;/.freeze
|
29
29
|
|
30
30
|
else
|
@@ -211,6 +211,7 @@ module Rack #:nodoc:
|
|
211
211
|
# use of digits anywhere in the 'language-range' (see [RFC2616errata]).
|
212
212
|
#++
|
213
213
|
|
214
|
+
# TODO: move to LanguageTag or Languages
|
214
215
|
HTTP_ACCEPT_LANGUAGE_REGEX = /^\s*(\*|[a-z]{1,8}(?:-[a-z\d]{1,8}|-\*)*)#{Utils::QUALITY_PATTERN}\s*$/io.freeze
|
215
216
|
|
216
217
|
def normalize_header(header)
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acceptable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- SSDany
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-07-01 00:00:00 +04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: rack
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
27
30
|
segments:
|
28
31
|
- 1
|
29
32
|
- 0
|
@@ -47,11 +50,14 @@ files:
|
|
47
50
|
- README.rdoc
|
48
51
|
- lib/rack/acceptable/const.rb
|
49
52
|
- lib/rack/acceptable/language_tag.rb
|
53
|
+
- lib/rack/acceptable/middleware/fake_accept.rb
|
50
54
|
- lib/rack/acceptable/middleware/formats.rb
|
51
55
|
- lib/rack/acceptable/middleware/provides.rb
|
52
|
-
- lib/rack/acceptable/middleware/fake_accept.rb
|
53
56
|
- lib/rack/acceptable/mimetypes.rb
|
57
|
+
- lib/rack/acceptable/mixin/charsets.rb
|
58
|
+
- lib/rack/acceptable/mixin/encodings.rb
|
54
59
|
- lib/rack/acceptable/mixin/headers.rb
|
60
|
+
- lib/rack/acceptable/mixin/languages.rb
|
55
61
|
- lib/rack/acceptable/mixin/media.rb
|
56
62
|
- lib/rack/acceptable/request.rb
|
57
63
|
- lib/rack/acceptable/utils.rb
|
@@ -68,23 +74,27 @@ rdoc_options: []
|
|
68
74
|
require_paths:
|
69
75
|
- lib
|
70
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
71
78
|
requirements:
|
72
79
|
- - ">="
|
73
80
|
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
74
82
|
segments:
|
75
83
|
- 0
|
76
84
|
version: "0"
|
77
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
78
87
|
requirements:
|
79
88
|
- - ">="
|
80
89
|
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
81
91
|
segments:
|
82
92
|
- 0
|
83
93
|
version: "0"
|
84
94
|
requirements: []
|
85
95
|
|
86
96
|
rubyforge_project: acceptable
|
87
|
-
rubygems_version: 1.3.
|
97
|
+
rubygems_version: 1.3.7
|
88
98
|
signing_key:
|
89
99
|
specification_version: 3
|
90
100
|
summary: HTTP Accept parsers for Rack.
|