tricycle-rack-contrib 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -50,11 +50,11 @@ interface:
50
50
 
51
51
  Git is the quickest way to the rack-contrib sources:
52
52
 
53
- git clone git://github.com/rack/rack-contrib.git
53
+ git clone git://github.com/tricycle/rack-contrib.git
54
54
 
55
- Gems are currently available from GitHub clones:
55
+ Gems are currently available from Gemcutter:
56
56
 
57
- gem install rack-rack-contrib --source=http://gems.github.com/
57
+ gem install tricycle-rack-contrib --source=http://gemcutter.org/
58
58
 
59
59
  Requiring 'rack/contrib' will add autoloads to the Rack modules for all of the
60
60
  components included. The following example shows what a simple rackup
@@ -73,6 +73,7 @@ components included. The following example shows what a simple rackup
73
73
  === Links
74
74
 
75
75
  rack-contrib on GitHub:: <http://github.com/rack/rack-contrib>
76
+ tricycle-rack-contrib on GitHub:: <http://github.com/tricycle/rack-contrib>
76
77
  Rack:: <http://rack.rubyforge.org/>
77
78
  Rack On GitHub:: <http://github.org/rack/rack>
78
79
  rack-devel mailing list:: <http://groups.google.com/group/rack-devel>
@@ -7,6 +7,18 @@ require 'rack'
7
7
  # Rails' page caching, allowing you to cache dynamic pages to static files that can
8
8
  # be served directly by a front end webserver.
9
9
  class Rack::ResponseCache
10
+ CONTENT_TYPES = {
11
+ "application/pdf" => %w[pdf],
12
+ "application/xhtml+xml" => %w[xhtml],
13
+ "text/css" => %w[css],
14
+ "text/csv" => %w[csv],
15
+ "text/html" => %w[html htm],
16
+ "text/javascript" => %w[js], "application/javascript" => %w[js],
17
+ "text/plain" => %w[txt],
18
+ "text/xml" => %w[xml],
19
+ }
20
+ ALLOWED_EXTENSIONS = CONTENT_TYPES.collect {|k, v| v }.flatten.uniq
21
+
10
22
  # The default proc used if a block is not provided to .new
11
23
  # Doesn't cache unless path does not contain '..', Content-Type is
12
24
  # whitelisted, and path agrees with Content-Type
@@ -15,34 +27,31 @@ class Rack::ResponseCache
15
27
  DEFAULT_PATH_PROC = proc do |env, res|
16
28
  path = Rack::Utils.unescape(env['PATH_INFO'])
17
29
 
18
- content_types = {
19
- "application/pdf" => %w[pdf],
20
- "application/xhtml+xml" => %w[xhtml],
21
- "text/css" => %w[css],
22
- "text/csv" => %w[csv],
23
- "text/html" => %w[html htm],
24
- "text/javascript" => %w[js], "application/javascript" => %w[js],
25
- "text/plain" => %w[txt],
26
- "text/xml" => %w[xml],
27
- }
28
- content_type = res[1]['Content-Type'].to_s
30
+ content_type = res[1]['Content-Type'].to_s.split(';').first
31
+ extension = File.extname(path)[1..-1]
29
32
 
30
- if !path.include?('..') and extensions = content_types[content_type]
33
+ if !path.include?('..') and (allowed_extensions_for_content_type = CONTENT_TYPES[content_type])
31
34
  # path doesn't include '..' and Content-Type is whitelisted
32
35
  case
33
36
  when path.match(/\/$/) && content_type == "text/html"
34
37
  # path ends in / and Content-Type is text/html
35
38
  path << "index.html"
36
- when File.extname(path) == ""
37
- # no extension
38
- path << ".#{extensions.first}"
39
- when !extensions.include?(File.extname(path)[1..-1])
40
- # extension agrees with Content-Type
39
+ when path.match(/\/$/) && content_type != "text/html"
40
+ # path ends in / and Content-Type is not text/html - don't cache
41
+ path = nil
42
+ when File.extname(path) == "" ||
43
+ (!ALLOWED_EXTENSIONS.include?(extension) && content_type == "text/html")
44
+ # no extension OR
45
+ # unrecognized extension AND content_type is text/html
46
+ path << ".#{allowed_extensions_for_content_type.first}"
47
+ when !allowed_extensions_for_content_type.include?(extension)
48
+ # extension doesn't agree with Content-Type (but extension is recognized) - don't cache
41
49
  path = nil
42
50
  else
43
51
  # do nothing, path is alright
44
52
  end
45
53
  else
54
+ # don't cache
46
55
  path = nil
47
56
  end
48
57
 
@@ -23,40 +23,40 @@ context Rack::ResponseCache do
23
23
  end
24
24
 
25
25
  specify "should cache results to disk if cache is a string" do
26
- request(:cache=>@def_disk_cache)
26
+ request(:cache => @def_disk_cache)
27
27
  F.read(F.join(@def_disk_cache, 'path', 'to', 'blah.html')).should.equal @def_value.first
28
- request(:path=>'/path/3', :cache=>@def_disk_cache)
28
+ request(:path => '/path/3', :cache => @def_disk_cache)
29
29
  F.read(F.join(@def_disk_cache, 'path', '3.html')).should.equal @def_value.first
30
30
  end
31
31
 
32
32
  specify "should cache results to given cache if cache is not a string" do
33
33
  request
34
- @cache.should.equal('/path/to/blah.html'=>@def_value)
35
- request(:path=>'/path/3')
36
- @cache.should.equal('/path/to/blah.html'=>@def_value, '/path/3.html'=>@def_value)
34
+ @cache.should.equal('/path/to/blah.html' => @def_value)
35
+ request(:path => '/path/3')
36
+ @cache.should.equal('/path/to/blah.html' => @def_value, '/path/3.html' => @def_value)
37
37
  end
38
38
 
39
39
  specify "should not cache results if request method is not GET" do
40
- request(:meth=>:post)
40
+ request(:meth => :post)
41
41
  @cache.should.equal({})
42
- request(:meth=>:put)
42
+ request(:meth => :put)
43
43
  @cache.should.equal({})
44
- request(:meth=>:delete)
44
+ request(:meth => :delete)
45
45
  @cache.should.equal({})
46
46
  end
47
47
 
48
- specify "should not cache results if there is a query string" do
49
- request(:path=>'/path/to/blah?id=1')
48
+ specify "should not cache results if there is a non-empty query string" do
49
+ request(:path => '/path/to/blah?id=1')
50
50
  @cache.should.equal({})
51
- request(:path=>'/path/to/?id=1')
51
+ request(:path => '/path/to/?id=1')
52
52
  @cache.should.equal({})
53
- request(:path=>'/?id=1')
53
+ request(:path => '/?id=1')
54
54
  @cache.should.equal({})
55
55
  end
56
56
 
57
57
  specify "should cache results if there is an empty query string" do
58
- request(:path=>'/?')
59
- @cache.should.equal('/index.html'=>@def_value)
58
+ request(:path => '/?')
59
+ @cache.should.equal('/index.html' => @def_value)
60
60
  end
61
61
 
62
62
  specify "should not cache results if the request is not sucessful (status 200)" do
@@ -95,38 +95,38 @@ context Rack::ResponseCache do
95
95
  end
96
96
 
97
97
  specify "should not cache results if the block returns nil or false" do
98
- request(:rc_block=>proc{false})
98
+ request(:rc_block => proc{false})
99
99
  @cache.should.equal({})
100
- request(:rc_block=>proc{nil})
100
+ request(:rc_block => proc{nil})
101
101
  @cache.should.equal({})
102
102
  end
103
103
 
104
104
  specify "should cache results to path returned by block" do
105
- request(:rc_block=>proc{"1"})
106
- @cache.should.equal("1"=>@def_value)
107
- request(:rc_block=>proc{"2"})
108
- @cache.should.equal("1"=>@def_value, "2"=>@def_value)
105
+ request(:rc_block => proc{"1"})
106
+ @cache.should.equal("1" => @def_value)
107
+ request(:rc_block => proc{"2"})
108
+ @cache.should.equal("1" => @def_value, "2" => @def_value)
109
109
  end
110
110
 
111
111
  specify "should pass the environment and response to the block" do
112
112
  e, r = nil, nil
113
- request(:rc_block=>proc{|env,res| e, r = env, res; nil})
113
+ request(:rc_block => proc{|env,res| e, r = env, res; nil})
114
114
  e['PATH_INFO'].should.equal @def_path
115
115
  e['REQUEST_METHOD'].should.equal 'GET'
116
116
  e['QUERY_STRING'].should.equal ''
117
- r.should.equal([200, {"Content-Type"=>"text/html"}, ["rack-response-cache"]])
117
+ r.should.equal([200, {"Content-Type" => "text/html"}, ["rack-response-cache"]])
118
118
  end
119
119
 
120
120
  specify "should unescape the path by default" do
121
- request(:path=>'/path%20with%20spaces')
122
- @cache.should.equal('/path with spaces.html'=>@def_value)
123
- request(:path=>'/path%3chref%3e')
124
- @cache.should.equal('/path with spaces.html'=>@def_value, '/path<href>.html'=>@def_value)
121
+ request(:path => '/path%20with%20spaces')
122
+ @cache.should.equal('/path with spaces.html' => @def_value)
123
+ request(:path => '/path%3chref%3e')
124
+ @cache.should.equal('/path with spaces.html' => @def_value, '/path<href>.html' => @def_value)
125
125
  end
126
126
 
127
127
  specify "should cache html mime_type without extension at .html" do
128
- request(:path=>'/a')
129
- @cache.should.equal('/a.html'=>@def_value)
128
+ request(:path => '/a')
129
+ @cache.should.equal('/a.html' => @def_value)
130
130
  end
131
131
 
132
132
  {
@@ -141,36 +141,58 @@ context Rack::ResponseCache do
141
141
  }.each do |extension, mime_types|
142
142
  mime_types.each do |mime_type|
143
143
  specify "should cache #{mime_type} responses with the extension ('#{extension}') unchanged" do
144
- request(:path=>"/a.#{extension}", :headers=>{'CT'=>mime_type})
145
- @cache.should.equal("/a.#{extension}"=>@def_value)
144
+ request(:path => "/a.#{extension}", :headers => {'CT' => mime_type})
145
+ @cache.should.equal("/a.#{extension}" => @def_value)
146
146
  end
147
147
 
148
148
  specify "should cache #{mime_type} responses with the relevant extension ('#{extension}') added if not already present" do
149
- request(:path=>'/a', :headers=>{'CT'=>mime_type})
150
- @cache.should.equal("/a.#{extension}"=>@def_value)
149
+ request(:path => '/a', :headers => {'CT' => mime_type})
150
+ @cache.should.equal("/a.#{extension}" => @def_value)
151
151
  end
152
152
  end
153
153
  end
154
154
 
155
155
  specify "should cache 'text/html' responses with the extension ('htm') unchanged" do
156
- request(:path=>"/a.htm", :headers=>{'CT'=>"text/html"})
157
- @cache.should.equal("/a.htm"=>@def_value)
156
+ request(:path => "/a.htm", :headers => {'CT' => "text/html"})
157
+ @cache.should.equal("/a.htm" => @def_value)
158
158
  end
159
159
 
160
160
  [:css, :xml, :xhtml, :js, :txt, :pdf, :csv].each do |extension|
161
161
  specify "should not cache if extension and content-type don't agree" do
162
- request(:path=>"/d.#{extension}", :headers=>{'CT'=>'text/html'})
162
+ request(:path => "/d.#{extension}", :headers => {'CT' => 'text/html'})
163
163
  @cache.should.equal({})
164
164
  end
165
165
  end
166
166
 
167
- specify "should cache html responses with empty basename to index.html by default" do
168
- request(:path=>'/')
169
- @cache.should.equal('/index.html'=>@def_value)
170
- request(:path=>'/blah/')
171
- @cache.should.equal('/index.html'=>@def_value, '/blah/index.html'=>@def_value)
172
- request(:path=>'/blah/2/')
173
- @cache.should.equal('/index.html'=>@def_value, '/blah/index.html'=>@def_value, '/blah/2/index.html'=>@def_value)
167
+ specify "should cache text/html responses with empty basename to index.html" do
168
+ request(:path => '/', :headers => {'CT' => "text/html"})
169
+ request(:path => '/blah/', :headers => {'CT' => "text/html"})
170
+ request(:path => '/blah/2/', :headers => {'CT' => "text/html"})
171
+ @cache.should.equal("/index.html" => @def_value,
172
+ "/blah/index.html" => @def_value,
173
+ "/blah/2/index.html" => @def_value)
174
+ end
175
+
176
+ specify "should not cache non-text/html responses with empty basename" do
177
+ request(:path => '/', :headers => {'CT' => "text/csv"})
178
+ request(:path => '/blah/', :headers => {'CT' => "text/css"})
179
+ request(:path => '/blah/2/', :headers => {'CT' => "text/plain"})
180
+ @cache.should.equal({})
181
+ end
182
+
183
+ specify "should cache unrecognized extensions with text/html content-type at .html" do
184
+ request(:path => "/a.seo", :headers => {'CT' => "text/html"})
185
+ @cache.should.equal("/a.seo.html" => @def_value)
186
+ end
187
+
188
+ specify "should not cache unrecognized content-types" do
189
+ request(:path => "/a", :headers => {'CT' => "text/unrecognised"})
190
+ @cache.should.equal({})
191
+ end
192
+
193
+ specify "should recognize content-types with supplied parameters (eg. charset)" do
194
+ request(:path => "/a", :headers => {'CT' => "text/html; charset=utf-8"})
195
+ @cache.should.equal("/a.html" => @def_value)
174
196
  end
175
197
 
176
198
  specify "should raise an error if a cache argument is not provided" do
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'tricycle-rack-contrib'
6
- s.version = '0.9.5'
7
- s.date = '2010-01-06'
6
+ s.version = '0.9.6'
7
+ s.date = '2010-01-07'
8
8
 
9
9
  s.description = "Contributed Rack Middleware and Utilities, including Tricycle's modifications"
10
10
  s.summary = "Contributed Rack Middleware and Utilities, including Tricycle's modifications"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tricycle-rack-contrib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - tricycle
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2010-01-06 00:00:00 +11:00
13
+ date: 2010-01-07 00:00:00 +11:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency