rack-accept_headers 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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