rack-accept_headers 0.5.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.
@@ -0,0 +1,73 @@
1
+ module Rack::AcceptHeaders
2
+ # Represents an HTTP Accept header according to the HTTP 1.1 specification,
3
+ # and provides several convenience methods for determining acceptable media
4
+ # types.
5
+ #
6
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
7
+ class MediaType
8
+ include Header
9
+
10
+ attr_accessor :extensions
11
+
12
+ # The name of this header.
13
+ def name
14
+ 'Accept'
15
+ end
16
+
17
+ # Determines the quality factor (qvalue) of the given +media_type+.
18
+ def qvalue(media_type)
19
+ return 1 if @qvalues.empty?
20
+ m = matches(media_type)
21
+ return 0 if m.empty?
22
+ normalize_qvalue(@qvalues[m.first])
23
+ end
24
+
25
+ # Returns an array of media types from this header that match the given
26
+ # +media_type+, ordered by precedence.
27
+ def matches(media_type)
28
+ type, subtype, params = parse_media_type(media_type)
29
+ values.select {|v|
30
+ if v == media_type || v == '*/*'
31
+ true
32
+ else
33
+ t, s, p = parse_media_type(v)
34
+ t == type && (s == '*' || s == subtype) && (p == '' || params_match?(params, p))
35
+ end
36
+ }.sort_by {|v|
37
+ # Most specific gets precedence.
38
+ v.length
39
+ }.reverse
40
+ end
41
+
42
+ # Returns a params hash for the media type that matches
43
+ def params(media_type)
44
+ return {} unless media_type
45
+ key = matches(media_type).first
46
+ @extensions[key] || {}
47
+ end
48
+
49
+ private
50
+
51
+ def initialize(header)
52
+ @extensions = {}
53
+ @qvalues = {}
54
+
55
+ header.to_s.split(',').each do |part|
56
+ type, subtype, raw_params = parse_media_type(part)
57
+ raise InvalidHeader, "Invalid header value: #{part.inspect}" if !type || !subtype
58
+ media_type = "#{type}/#{subtype}"
59
+ params = parse_range_params(raw_params)
60
+ @extensions[media_type] = params
61
+ @qvalues[media_type] = normalize_qvalue(params['q']).to_f
62
+ end
63
+ end
64
+
65
+ # Returns true if all parameters and values in +match+ are also present in
66
+ # +params+.
67
+ def params_match?(params, match)
68
+ return true if params == match
69
+ parsed = parse_range_params(params)
70
+ parsed == parsed.merge(parse_range_params(match))
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,90 @@
1
+ require 'rack/request'
2
+
3
+ module Rack::AcceptHeaders
4
+ # A container class for convenience methods when Rack::AcceptHeaders is used on the
5
+ # request level as Rack middleware. Instances of this class also manage a
6
+ # lightweight cache of various header instances to speed up execution.
7
+ class Request < Rack::Request
8
+ attr_reader :env
9
+
10
+ def initialize(env)
11
+ @env = env
12
+ end
13
+
14
+ # Provides access to the Rack::AcceptHeaders::MediaType instance for this request.
15
+ def media_type
16
+ @media_type ||= MediaType.new(env['HTTP_ACCEPT'])
17
+ end
18
+
19
+ # Provides access to the Rack::AcceptHeaders::Charset instance for this request.
20
+ def charset
21
+ @charset ||= Charset.new(env['HTTP_ACCEPT_CHARSET'])
22
+ end
23
+
24
+ # Provides access to the Rack::AcceptHeaders::Encoding instance for this request.
25
+ def encoding
26
+ @encoding ||= Encoding.new(env['HTTP_ACCEPT_ENCODING'])
27
+ end
28
+
29
+ # Provides access to the Rack::AcceptHeaders::Language instance for this request.
30
+ def language
31
+ @language ||= Language.new(env['HTTP_ACCEPT_LANGUAGE'])
32
+ end
33
+
34
+ # Returns true if the +Accept+ request header indicates the given media
35
+ # type is acceptable, false otherwise.
36
+ def media_type?(value)
37
+ media_type.accept?(value)
38
+ end
39
+
40
+ # Returns true if the +Accept-Charset+ request header indicates the given
41
+ # character set is acceptable, false otherwise.
42
+ def charset?(value)
43
+ charset.accept?(value)
44
+ end
45
+
46
+ # Returns true if the +Accept-Encoding+ request header indicates the given
47
+ # encoding is acceptable, false otherwise.
48
+ def encoding?(value)
49
+ encoding.accept?(value)
50
+ end
51
+
52
+ # Returns true if the +Accept-Language+ request header indicates the given
53
+ # language is acceptable, false otherwise.
54
+ def language?(value)
55
+ language.accept?(value)
56
+ end
57
+
58
+ # Determines the best media type to use in a response from the given media
59
+ # types, if any is acceptable. For more information on how this value is
60
+ # determined, see the documentation for
61
+ # Rack::AcceptHeaders::Header::PublicInstanceMethods#sort.
62
+ def best_media_type(values)
63
+ media_type.best_of(values)
64
+ end
65
+
66
+ # Determines the best character set to use in a response from the given
67
+ # character sets, if any is acceptable. For more information on how this
68
+ # value is determined, see the documentation for
69
+ # Rack::AcceptHeaders::Header::PublicInstanceMethods#sort.
70
+ def best_charset(values)
71
+ charset.best_of(values)
72
+ end
73
+
74
+ # Determines the best encoding to use in a response from the given
75
+ # encodings, if any is acceptable. For more information on how this value
76
+ # is determined, see the documentation for
77
+ # Rack::AcceptHeaders::Header::PublicInstanceMethods#sort.
78
+ def best_encoding(values)
79
+ encoding.best_of(values)
80
+ end
81
+
82
+ # Determines the best language to use in a response from the given
83
+ # languages, if any is acceptable. For more information on how this value
84
+ # is determined, see the documentation for
85
+ # Rack::AcceptHeaders::Header::PublicInstanceMethods#sort.
86
+ def best_language(values)
87
+ language.best_of(values)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,18 @@
1
+ require 'rack/response'
2
+
3
+ module Rack::AcceptHeaders
4
+ # The base class for responses issued by Rack::AcceptHeaders.
5
+ class Response < Rack::Response
6
+ # Marks this response as being unacceptable and clears the response body.
7
+ #
8
+ # Note: The HTTP spec advises servers to respond with an "entity" that
9
+ # describes acceptable parameters, but it fails to go into detail about its
10
+ # implementation. Thus, it is up to the user of this library to create such
11
+ # an entity if one is desired.
12
+ def not_acceptable!
13
+ self.status = 406
14
+ self.body = []
15
+ header['Content-Length'] = '0'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ module AcceptHeaders
3
+ VERSION = '0.5.0'
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'rack'
2
+ require 'rack/accept_headers/header'
3
+ require 'rack/accept_headers/charset'
4
+ require 'rack/accept_headers/context'
5
+ require 'rack/accept_headers/encoding'
6
+ require 'rack/accept_headers/language'
7
+ require 'rack/accept_headers/media_type'
8
+ require 'rack/accept_headers/request'
9
+ require 'rack/accept_headers/response'
10
+
11
+ module Rack::AcceptHeaders
12
+ # Enables Rack::AcceptHeaders to be used as a Rack middleware.
13
+ def self.new(app, &block)
14
+ Context.new(app, &block)
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'rack/accept_headers/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rack-accept_headers"
7
+ spec.version = Rack::AcceptHeaders::VERSION
8
+ spec.authors = ["Jack Chu", "Michael Jackson"]
9
+ spec.email = ["kamuigt@gmail.com", "mjijackson@gmail.com"]
10
+ spec.summary = %q{HTTP Accept* for Ruby/Rack}
11
+ spec.description = %q{HTTP Accept, Accept-Charset, Accept-Encoding, and Accept-Language for Ruby/Rack}
12
+ spec.homepage = "https://github.com/kamui/rack-accept_headers"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'rack'
21
+
22
+ spec.add_development_dependency 'bundler'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'minitest'
25
+ spec.add_development_dependency 'guard'
26
+ spec.add_development_dependency 'guard-minitest'
27
+ end
@@ -0,0 +1,43 @@
1
+ require_relative 'test_helper'
2
+
3
+ class CharsetTest < Minitest::Test
4
+ C = Rack::AcceptHeaders::Charset
5
+
6
+ def test_qvalue
7
+ c = C.new('')
8
+ assert_equal(0, c.qvalue('unicode-1-1'))
9
+ assert_equal(1, c.qvalue('iso-8859-1'))
10
+
11
+ c = C.new('unicode-1-1')
12
+ assert_equal(1, c.qvalue('unicode-1-1'))
13
+ assert_equal(0, c.qvalue('iso-8859-5'))
14
+ assert_equal(1, c.qvalue('iso-8859-1'))
15
+
16
+ c = C.new('unicode-1-1, *;q=0.5')
17
+ assert_equal(1, c.qvalue('unicode-1-1'))
18
+ assert_equal(0.5, c.qvalue('iso-8859-5'))
19
+ assert_equal(0.5, c.qvalue('iso-8859-1'))
20
+
21
+ c = C.new('iso-8859-1;q=0, *;q=0.5')
22
+ assert_equal(0.5, c.qvalue('iso-8859-5'))
23
+ assert_equal(0, c.qvalue('iso-8859-1'))
24
+
25
+ c = C.new('*;q=0')
26
+ assert_equal(0, c.qvalue('iso-8859-1'))
27
+ end
28
+
29
+ def test_matches
30
+ c = C.new('iso-8859-1, iso-8859-5, *')
31
+ assert_equal(%w{*}, c.matches(''))
32
+ assert_equal(%w{iso-8859-1 *}, c.matches('iso-8859-1'))
33
+ assert_equal(%w{*}, c.matches('unicode-1-1'))
34
+ end
35
+
36
+ def test_best_of
37
+ c = C.new('iso-8859-5, unicode-1-1;q=0.8')
38
+ assert_equal('iso-8859-5', c.best_of(%w< iso-8859-5 unicode-1-1 >))
39
+ assert_equal('iso-8859-5', c.best_of(%w< iso-8859-5 utf-8 >))
40
+ assert_equal('iso-8859-1', c.best_of(%w< iso-8859-1 utf-8 >))
41
+ assert_equal(nil, c.best_of(%w< utf-8 >))
42
+ end
43
+ end
@@ -0,0 +1,57 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ContextTest < Minitest::Test
4
+ def media_types; Proc.new {|c| c.media_types = %w< text/html > } end
5
+ def charsets; Proc.new {|c| c.charsets = %w< iso-8859-5 > } end
6
+ def encodings; Proc.new {|c| c.encodings = %w< gzip > } end
7
+ def languages; Proc.new {|c| c.languages = %w< en > } end
8
+
9
+ def test_empty
10
+ request
11
+ assert_equal(200, status)
12
+ end
13
+
14
+ def test_media_types
15
+ request('HTTP_ACCEPT' => 'text/html')
16
+ assert_equal(200, status)
17
+
18
+ request('HTTP_ACCEPT' => 'text/html', &media_types)
19
+ assert_equal(200, status)
20
+
21
+ request('HTTP_ACCEPT' => 'text/plain', &media_types)
22
+ assert_equal(406, status)
23
+ end
24
+
25
+ def test_charsets
26
+ request('HTTP_ACCEPT_CHARSET' => 'iso-8859-5')
27
+ assert_equal(200, status)
28
+
29
+ request('HTTP_ACCEPT_CHARSET' => 'iso-8859-5', &charsets)
30
+ assert_equal(200, status)
31
+
32
+ request('HTTP_ACCEPT_CHARSET' => 'unicode-1-1', &charsets)
33
+ assert_equal(406, status)
34
+ end
35
+
36
+ def test_encodings
37
+ request('HTTP_ACCEPT_ENCODING' => 'gzip')
38
+ assert_equal(200, status)
39
+
40
+ request('HTTP_ACCEPT_ENCODING' => 'gzip', &encodings)
41
+ assert_equal(200, status)
42
+
43
+ request('HTTP_ACCEPT_ENCODING' => 'compress', &encodings)
44
+ assert_equal(406, status)
45
+ end
46
+
47
+ def test_languages
48
+ request('HTTP_ACCEPT_LANGUAGE' => 'en')
49
+ assert_equal(200, status)
50
+
51
+ request('HTTP_ACCEPT_LANGUAGE' => 'en', &languages)
52
+ assert_equal(200, status)
53
+
54
+ request('HTTP_ACCEPT_LANGUAGE' => 'jp', &languages)
55
+ assert_equal(406, status)
56
+ end
57
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'test_helper'
2
+
3
+ class EncodingTest < Minitest::Test
4
+ E = Rack::AcceptHeaders::Encoding
5
+
6
+ def test_qvalue
7
+ e = E.new('')
8
+ assert_equal(0, e.qvalue('gzip'))
9
+ assert_equal(1, e.qvalue('identity'))
10
+
11
+ e = E.new('gzip, *;q=0.5')
12
+ assert_equal(1, e.qvalue('gzip'))
13
+ assert_equal(0.5, e.qvalue('identity'))
14
+ end
15
+
16
+ def test_matches
17
+ e = E.new('gzip, identity, *')
18
+ assert_equal(%w{*}, e.matches(''))
19
+ assert_equal(%w{gzip *}, e.matches('gzip'))
20
+ assert_equal(%w{*}, e.matches('compress'))
21
+ end
22
+
23
+ def test_best_of
24
+ e = E.new('gzip, compress')
25
+ assert_equal('gzip', e.best_of(%w< gzip compress >))
26
+ assert_equal('identity', e.best_of(%w< identity compress >))
27
+ assert_equal(nil, e.best_of(%w< zip >))
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ require_relative 'test_helper'
2
+
3
+ class HeaderTest < Minitest::Test
4
+ H = Rack::AcceptHeaders::Header
5
+
6
+ def test_parse_and_join
7
+ # Accept
8
+ header = 'text/plain; q=0.5, text/html, text/html;level=2, text/html;level=1;q=0.3, text/x-c, image/*; q=0.2'
9
+ expect = {
10
+ 'text/plain' => 0.5,
11
+ 'text/html' => 1,
12
+ 'text/html;level=2' => 1,
13
+ 'text/html;level=1' => 0.3,
14
+ 'text/x-c' => 1,
15
+ 'image/*' => 0.2
16
+ }
17
+ assert_equal(expect, H.parse(header))
18
+ assert_equal(expect, H.parse(H.join(expect)))
19
+
20
+ # Accept-Charset
21
+ header = 'iso-8859-5, unicode-1-1;q=0.8'
22
+ expect = { 'iso-8859-5' => 1, 'unicode-1-1' => 0.8 }
23
+ assert_equal(expect, H.parse(header))
24
+ assert_equal(expect, H.parse(H.join(expect)))
25
+
26
+ # Accept-Encoding
27
+ header = 'gzip;q=1.0, identity; q=0.5, *;q=0'
28
+ expect = { 'gzip' => 1, 'identity' => 0.5, '*' => 0 }
29
+ assert_equal(expect, H.parse(header))
30
+ assert_equal(expect, H.parse(H.join(expect)))
31
+
32
+ # Accept-Language
33
+ header = 'da, en-gb;q=0.8, en;q=0.7'
34
+ expect = { 'da' => 1, 'en-gb' => 0.8, 'en' => 0.7 }
35
+ assert_equal(expect, H.parse(header))
36
+ assert_equal(expect, H.parse(H.join(expect)))
37
+ end
38
+
39
+ def test_parse_media_type
40
+ assert_equal([], H.parse_media_type(''))
41
+ assert_equal(['*', '*', ''], H.parse_media_type('*/*'))
42
+ assert_equal(['text', '*', ''], H.parse_media_type('text/*'))
43
+ assert_equal(['text', 'html', ''], H.parse_media_type('text/html'))
44
+ assert_equal(['text', 'html', 'level=1'], H.parse_media_type('text/html;level=1'))
45
+ assert_equal(['text', 'html', 'level=1;answer=42'], H.parse_media_type('text/html;level=1;answer=42'))
46
+ assert_equal(['text', 'x-dvi', ''], H.parse_media_type('text/x-dvi'))
47
+ end
48
+
49
+ def test_parse_range_params
50
+ assert_equal({'q' => '1'}, H.parse_range_params(''))
51
+ assert_equal({'q' => '1'}, H.parse_range_params('a'))
52
+ assert_equal({'q' => '1', 'a' => 'a'}, H.parse_range_params('a=a'))
53
+ assert_equal({'q' => '1', 'a' => 'a', 'b' => 'b'}, H.parse_range_params('a=a;b=b'))
54
+ end
55
+
56
+ def test_normalize_qvalue
57
+ assert_equal(1, H.normalize_qvalue(1.0))
58
+ assert_equal(0, H.normalize_qvalue(0.0))
59
+ assert_equal(1, H.normalize_qvalue(1))
60
+ assert_equal(0, H.normalize_qvalue(0))
61
+ assert_equal(0.5, H.normalize_qvalue(0.5))
62
+ end
63
+
64
+ def test_invalid_header
65
+ assert_raises Rack::AcceptHeaders::Header::InvalidHeader do
66
+ h = H.parse(' / ')
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,47 @@
1
+ require_relative 'test_helper'
2
+
3
+ class LanguageTest < Minitest::Test
4
+ L = Rack::AcceptHeaders::Language
5
+
6
+ def test_qvalue
7
+ l = L.new('')
8
+ assert_equal(1, l.qvalue('en'))
9
+
10
+ l = L.new('en;q=0.5, en-gb')
11
+ assert_equal(0.5, l.qvalue('en'))
12
+ assert_equal(1, l.qvalue('en-gb'))
13
+ assert_equal(0, l.qvalue('da'))
14
+ end
15
+
16
+ def test_matches
17
+ l = L.new('da, *, en')
18
+ assert_equal(%w{*}, l.matches(''))
19
+ assert_equal(%w{da *}, l.matches('da'))
20
+ assert_equal(%w{en *}, l.matches('en'))
21
+ assert_equal(%w{en *}, l.matches('en-gb'))
22
+ assert_equal(%w{*}, l.matches('eng'))
23
+
24
+ l = L.new('en, en-gb')
25
+ assert_equal(%w{en-gb en}, l.matches('en-gb'))
26
+ end
27
+
28
+ def test_best_of
29
+ l = L.new('en;q=0.5, en-gb')
30
+ assert_equal('en-gb', l.best_of(%w< en en-gb >))
31
+ assert_equal('en', l.best_of(%w< en da >))
32
+ assert_equal('en-us', l.best_of(%w< en-us en-au >))
33
+ assert_equal(nil, l.best_of(%w< da >))
34
+
35
+ l = L.new('en;q=0.5, en-GB, fr-CA')
36
+ assert_equal('en-gb', l.best_of(%w< en en-gb >))
37
+
38
+ l = L.new('en-gb;q=0.5, EN, fr-CA')
39
+ assert_equal('en', l.best_of(%w< en en-gb >))
40
+
41
+ l = L.new('en;q=0.5, fr-ca')
42
+ assert_equal('en', l.best_of(%w< en fr >))
43
+
44
+ l.first_level_match = true
45
+ assert_equal('fr', l.best_of(%w< en fr >))
46
+ end
47
+ end
@@ -0,0 +1,80 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MediaTypeTest < Minitest::Test
4
+ M = Rack::AcceptHeaders::MediaType
5
+
6
+ def test_qvalue
7
+ m = M.new('text/html, text/*;q=0.3, */*;q=0.5')
8
+ assert_equal(0.5, m.qvalue('image/png'))
9
+ assert_equal(0.3, m.qvalue('text/plain'))
10
+ assert_equal(1, m.qvalue('text/html'))
11
+
12
+ m = M.new('text/html')
13
+ assert_equal(0, m.qvalue('image/png'))
14
+
15
+ m = M.new('')
16
+ assert_equal(1, m.qvalue('text/html'))
17
+ end
18
+
19
+ def test_invalid_media_type
20
+ assert_raises Rack::AcceptHeaders::Header::InvalidHeader do
21
+ m = M.new('')
22
+ m = M.new('text')
23
+ m = M.new('text;q=1')
24
+ end
25
+ end
26
+
27
+ def test_matches
28
+ m = M.new('text/*, text/html, text/html;level=1, */*')
29
+ assert_equal(%w{*/*}, m.matches(''))
30
+ assert_equal(%w{*/*}, m.matches('image/jpeg'))
31
+ assert_equal(%w{text/* */*}, m.matches('text/plain'))
32
+ assert_equal(%w{text/html text/* */*}, m.matches('text/html'))
33
+ assert_equal(%w{text/html text/* */*}, m.matches('text/html;level=1'))
34
+ assert_equal(%w{text/html text/* */*}, m.matches('text/html;level=1;answer=42'))
35
+ end
36
+
37
+ def test_best_of
38
+ m = M.new('text/*;q=0.5, text/html')
39
+ assert_equal('text/html', m.best_of(%w< text/plain text/html >))
40
+ assert_equal('text/plain', m.best_of(%w< text/plain image/png >))
41
+ assert_equal('text/plain', m.best_of(%w< text/plain text/javascript >))
42
+ assert_equal(nil, m.best_of(%w< image/png >))
43
+
44
+ m = M.new('text/*')
45
+ assert_equal('text/html', m.best_of(%w< text/html text/xml >))
46
+ assert_equal('text/xml', m.best_of(%w< text/xml text/html >))
47
+
48
+ m = M.new('TEXT/*')
49
+ assert_equal('text/html', m.best_of(%w< text/html text/xml >))
50
+ assert_equal('text/xml', m.best_of(%w< text/xml text/html >))
51
+ end
52
+
53
+ def test_extensions
54
+ m = M.new('text/plain')
55
+ assert_equal({'text/plain' => {'q' => '1'}}, m.extensions)
56
+ m = M.new('text/*;q=0.5;a=42')
57
+ assert_equal({'text/*' => {'q' => '0.5', 'a' => '42'}}, m.extensions)
58
+ end
59
+
60
+ def test_params
61
+ m = M.new('text/plain;q=0.7;version=1.0')
62
+ assert_equal({'q' => '0.7', 'version' => '1.0'}, m.params('text/plain'))
63
+ m = M.new('text/*;q=0.5;a=42, application/json;b=12')
64
+ assert_equal({'q' => '0.5', 'a' => '42'}, m.params('text/plain'))
65
+ assert_equal({'q' => '1', 'b' => '12'}, m.params('application/json'))
66
+ end
67
+
68
+ def test_vendored_types
69
+ m = M.new("application/vnd.ms-excel")
70
+ assert_equal(nil, m.best_of(%w< application/vnd.ms-powerpoint >))
71
+
72
+ m = M.new("application/vnd.api-v1+json")
73
+ assert_equal(false, m.accept?("application/vnd.api-v2+json"))
74
+
75
+ v1, v2 = "application/vnd.api-v1+json", "application/vnd.api-v2+json"
76
+ m = M.new("#{v1},#{v2}")
77
+ assert_equal(v1, m.best_of([v1, v2]))
78
+ assert_equal(v2, m.best_of([v2, v1]))
79
+ end
80
+ end
@@ -0,0 +1,60 @@
1
+ require_relative 'test_helper'
2
+
3
+ class RequestTest < Minitest::Test
4
+ R = Rack::AcceptHeaders::Request
5
+
6
+ def test_media_type
7
+ r = R.new('HTTP_ACCEPT' => 'text/*;q=0, text/html')
8
+ assert(r.media_type?('text/html'))
9
+ assert(r.media_type?('text/html;level=1'))
10
+ assert(!r.media_type?('text/plain'))
11
+ assert(!r.media_type?('image/png'))
12
+
13
+ request = R.new('HTTP_ACCEPT' => '*/*')
14
+ assert(request.media_type?('image/png'))
15
+ end
16
+
17
+ def test_charset
18
+ r = R.new('HTTP_ACCEPT_CHARSET' => 'iso-8859-5, unicode-1-1;q=0.8')
19
+ assert(r.charset?('iso-8859-5'))
20
+ assert(r.charset?('unicode-1-1'))
21
+ assert(r.charset?('iso-8859-1'))
22
+ assert(!r.charset?('utf-8'))
23
+
24
+ r = R.new('HTTP_ACCEPT_CHARSET' => 'iso-8859-1;q=0')
25
+ assert(!r.charset?('iso-8859-1'))
26
+ end
27
+
28
+ def test_encoding
29
+ r = R.new('HTTP_ACCEPT_ENCODING' => '')
30
+ assert(r.encoding?('identity'))
31
+ assert(!r.encoding?('gzip'))
32
+
33
+ r = R.new('HTTP_ACCEPT_ENCODING' => 'gzip')
34
+ assert(r.encoding?('identity'))
35
+ assert(r.encoding?('gzip'))
36
+ assert(!r.encoding?('compress'))
37
+
38
+ r = R.new('HTTP_ACCEPT_ENCODING' => 'gzip;q=0, *')
39
+ assert(r.encoding?('compress'))
40
+ assert(r.encoding?('identity'))
41
+ assert(!r.encoding?('gzip'))
42
+
43
+ r = R.new('HTTP_ACCEPT_ENCODING' => 'identity;q=0')
44
+ assert(!r.encoding?('identity'))
45
+
46
+ r = R.new('HTTP_ACCEPT_ENCODING' => '*;q=0')
47
+ assert(!r.encoding?('identity'))
48
+ end
49
+
50
+ def test_language
51
+ request = R.new({})
52
+ assert(request.language?('en'))
53
+ assert(request.language?('da'))
54
+
55
+ request = R.new('HTTP_ACCEPT_LANGUAGE' => 'en;q=0.5, en-gb')
56
+ assert(request.language?('en'))
57
+ assert(request.language?('en-gb'))
58
+ assert(!request.language?('da'))
59
+ end
60
+ end
@@ -0,0 +1,26 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'rack'
4
+ require 'minitest/autorun'
5
+ require 'rack/accept_headers'
6
+
7
+ class Minitest::Test
8
+ attr_reader :context
9
+ attr_reader :response
10
+
11
+ def status
12
+ @response && @response.status
13
+ end
14
+
15
+ def request(env={}, method='GET', uri='/')
16
+ @context = Rack::AcceptHeaders.new(fake_app)
17
+ yield @context if block_given?
18
+ mock_request = Rack::MockRequest.new(@context)
19
+ @response = mock_request.request(method.to_s.upcase, uri, env)
20
+ @response
21
+ end
22
+
23
+ def fake_app(status=200, headers={}, body=[])
24
+ lambda {|env| Rack::Response.new(body, status, headers).finish }
25
+ end
26
+ end