rack 1.4.1 → 1.4.5

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.
Files changed (84) hide show
  1. data/COPYING +1 -1
  2. data/KNOWN-ISSUES +9 -0
  3. data/README.rdoc +105 -7
  4. data/Rakefile +18 -11
  5. data/SPEC +3 -1
  6. data/contrib/rack.png +0 -0
  7. data/contrib/rack.svg +150 -0
  8. data/contrib/rdoc.css +412 -0
  9. data/lib/rack/auth/abstract/request.rb +5 -1
  10. data/lib/rack/auth/basic.rb +1 -1
  11. data/lib/rack/auth/digest/nonce.rb +1 -1
  12. data/lib/rack/backports/uri/common_18.rb +14 -28
  13. data/lib/rack/backports/uri/common_192.rb +14 -17
  14. data/lib/rack/backports/uri/common_193.rb +29 -0
  15. data/lib/rack/body_proxy.rb +10 -0
  16. data/lib/rack/builder.rb +1 -1
  17. data/lib/rack/cascade.rb +11 -0
  18. data/lib/rack/commonlogger.rb +18 -5
  19. data/lib/rack/deflater.rb +5 -1
  20. data/lib/rack/directory.rb +1 -1
  21. data/lib/rack/etag.rb +6 -3
  22. data/lib/rack/file.rb +19 -15
  23. data/lib/rack/head.rb +1 -0
  24. data/lib/rack/lint.rb +3 -1
  25. data/lib/rack/lock.rb +3 -4
  26. data/lib/rack/mime.rb +1 -1
  27. data/lib/rack/mock.rb +3 -2
  28. data/lib/rack/multipart/parser.rb +16 -7
  29. data/lib/rack/multipart.rb +2 -2
  30. data/lib/rack/reloader.rb +1 -1
  31. data/lib/rack/request.rb +2 -4
  32. data/lib/rack/response.rb +2 -1
  33. data/lib/rack/server.rb +28 -2
  34. data/lib/rack/session/abstract/id.rb +5 -0
  35. data/lib/rack/session/cookie.rb +10 -1
  36. data/lib/rack/static.rb +90 -8
  37. data/lib/rack/utils.rb +28 -10
  38. data/lib/rack.rb +12 -0
  39. data/rack.gemspec +3 -3
  40. data/test/builder/line.ru +1 -0
  41. data/test/cgi/assets/folder/test.js +1 -0
  42. data/test/cgi/assets/fonts/font.eot +1 -0
  43. data/test/cgi/assets/images/image.png +1 -0
  44. data/test/cgi/assets/index.html +1 -0
  45. data/test/cgi/assets/javascripts/app.js +1 -0
  46. data/test/cgi/assets/stylesheets/app.css +1 -0
  47. data/test/spec_auth.rb +57 -0
  48. data/test/spec_auth_basic.rb +8 -0
  49. data/test/spec_auth_digest.rb +14 -0
  50. data/test/spec_body_proxy.rb +4 -0
  51. data/test/spec_builder.rb +7 -1
  52. data/test/spec_cascade.rb +8 -0
  53. data/test/spec_chunked.rb +6 -6
  54. data/test/spec_config.rb +0 -1
  55. data/test/spec_content_length.rb +26 -13
  56. data/test/spec_content_type.rb +15 -5
  57. data/test/spec_deflater.rb +35 -17
  58. data/test/spec_directory.rb +20 -1
  59. data/test/spec_etag.rb +29 -13
  60. data/test/spec_file.rb +42 -25
  61. data/test/spec_head.rb +25 -7
  62. data/test/spec_lobster.rb +20 -5
  63. data/test/spec_lock.rb +46 -21
  64. data/test/spec_logger.rb +2 -7
  65. data/test/spec_methodoverride.rb +21 -22
  66. data/test/spec_mock.rb +12 -7
  67. data/test/spec_multipart.rb +82 -0
  68. data/test/spec_nulllogger.rb +13 -2
  69. data/test/spec_recursive.rb +12 -9
  70. data/test/spec_request.rb +2 -2
  71. data/test/spec_response.rb +30 -0
  72. data/test/spec_runtime.rb +15 -5
  73. data/test/spec_sendfile.rb +13 -9
  74. data/test/spec_server.rb +47 -0
  75. data/test/spec_session_cookie.rb +68 -1
  76. data/test/spec_session_memcache.rb +10 -8
  77. data/test/spec_session_pool.rb +13 -10
  78. data/test/spec_showexceptions.rb +9 -4
  79. data/test/spec_showstatus.rb +10 -5
  80. data/test/spec_static.rb +85 -9
  81. data/test/spec_urlmap.rb +10 -10
  82. data/test/spec_utils.rb +19 -1
  83. data/test/static/another/index.html +1 -0
  84. metadata +23 -8
data/test/spec_static.rb CHANGED
@@ -1,22 +1,27 @@
1
1
  require 'rack/static'
2
+ require 'rack/lint'
2
3
  require 'rack/mock'
3
4
 
4
5
  class DummyApp
5
6
  def call(env)
6
- [200, {}, ["Hello World"]]
7
+ [200, {"Content-Type" => "text/plain"}, ["Hello World"]]
7
8
  end
8
9
  end
9
10
 
10
11
  describe Rack::Static do
12
+ def static(app, *args)
13
+ Rack::Lint.new Rack::Static.new(app, *args)
14
+ end
15
+
11
16
  root = File.expand_path(File.dirname(__FILE__))
12
17
 
13
18
  OPTIONS = {:urls => ["/cgi"], :root => root}
14
- STATIC_OPTIONS = {:urls => [""], :root => root, :index => 'static/index.html'}
19
+ STATIC_OPTIONS = {:urls => [""], :root => "#{root}/static", :index => 'index.html'}
15
20
  HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root}
16
21
 
17
- @request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, OPTIONS))
18
- @static_request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, STATIC_OPTIONS))
19
- @hash_request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, HASH_OPTIONS))
22
+ @request = Rack::MockRequest.new(static(DummyApp.new, OPTIONS))
23
+ @static_request = Rack::MockRequest.new(static(DummyApp.new, STATIC_OPTIONS))
24
+ @hash_request = Rack::MockRequest.new(static(DummyApp.new, HASH_OPTIONS))
20
25
 
21
26
  it "serves files" do
22
27
  res = @request.get("/cgi/test")
@@ -35,12 +40,19 @@ describe Rack::Static do
35
40
  res.body.should == "Hello World"
36
41
  end
37
42
 
38
- it "calls index file when requesting root" do
43
+ it "calls index file when requesting root in the given folder" do
39
44
  res = @static_request.get("/")
40
45
  res.should.be.ok
41
46
  res.body.should =~ /index!/
47
+
48
+ res = @static_request.get("/other/")
49
+ res.should.be.not_found
50
+
51
+ res = @static_request.get("/another/")
52
+ res.should.be.ok
53
+ res.body.should =~ /another index!/
42
54
  end
43
-
55
+
44
56
  it "doesn't call index file if :index option was omitted" do
45
57
  res = @request.get("/")
46
58
  res.body.should == "Hello World"
@@ -58,12 +70,76 @@ describe Rack::Static do
58
70
  res.body.should == "Hello World"
59
71
  end
60
72
 
61
- it "supports serving fixed cache-control" do
73
+ it "supports serving fixed cache-control (legacy option)" do
62
74
  opts = OPTIONS.merge(:cache_control => 'public')
63
- request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, opts))
75
+ request = Rack::MockRequest.new(static(DummyApp.new, opts))
64
76
  res = request.get("/cgi/test")
65
77
  res.should.be.ok
66
78
  res.headers['Cache-Control'].should == 'public'
67
79
  end
68
80
 
81
+ HEADER_OPTIONS = {:urls => ["/cgi"], :root => root, :header_rules => [
82
+ [:all, {'Cache-Control' => 'public, max-age=100'}],
83
+ [:fonts, {'Cache-Control' => 'public, max-age=200'}],
84
+ [%w(png jpg), {'Cache-Control' => 'public, max-age=300'}],
85
+ ['/cgi/assets/folder/', {'Cache-Control' => 'public, max-age=400'}],
86
+ ['cgi/assets/javascripts', {'Cache-Control' => 'public, max-age=500'}],
87
+ [/\.(css|erb)\z/, {'Cache-Control' => 'public, max-age=600'}]
88
+ ]}
89
+ @header_request = Rack::MockRequest.new(static(DummyApp.new, HEADER_OPTIONS))
90
+
91
+ it "supports header rule :all" do
92
+ # Headers for all files via :all shortcut
93
+ res = @header_request.get('/cgi/assets/index.html')
94
+ res.should.be.ok
95
+ res.headers['Cache-Control'].should == 'public, max-age=100'
96
+ end
97
+
98
+ it "supports header rule :fonts" do
99
+ # Headers for web fonts via :fonts shortcut
100
+ res = @header_request.get('/cgi/assets/fonts/font.eot')
101
+ res.should.be.ok
102
+ res.headers['Cache-Control'].should == 'public, max-age=200'
103
+ end
104
+
105
+ it "supports file extension header rules provided as an Array" do
106
+ # Headers for file extensions via array
107
+ res = @header_request.get('/cgi/assets/images/image.png')
108
+ res.should.be.ok
109
+ res.headers['Cache-Control'].should == 'public, max-age=300'
110
+ end
111
+
112
+ it "supports folder rules provided as a String" do
113
+ # Headers for files in folder via string
114
+ res = @header_request.get('/cgi/assets/folder/test.js')
115
+ res.should.be.ok
116
+ res.headers['Cache-Control'].should == 'public, max-age=400'
117
+ end
118
+
119
+ it "supports folder header rules provided as a String not starting with a slash" do
120
+ res = @header_request.get('/cgi/assets/javascripts/app.js')
121
+ res.should.be.ok
122
+ res.headers['Cache-Control'].should == 'public, max-age=500'
123
+ end
124
+
125
+ it "supports flexible header rules provided as Regexp" do
126
+ # Flexible Headers via Regexp
127
+ res = @header_request.get('/cgi/assets/stylesheets/app.css')
128
+ res.should.be.ok
129
+ res.headers['Cache-Control'].should == 'public, max-age=600'
130
+ end
131
+
132
+ it "prioritizes header rules over fixed cache-control setting (legacy option)" do
133
+ opts = OPTIONS.merge(
134
+ :cache_control => 'public, max-age=24',
135
+ :header_rules => [
136
+ [:all, {'Cache-Control' => 'public, max-age=42'}]
137
+ ])
138
+
139
+ request = Rack::MockRequest.new(static(DummyApp.new, opts))
140
+ res = request.get("/cgi/test")
141
+ res.should.be.ok
142
+ res.headers['Cache-Control'].should == 'public, max-age=42'
143
+ end
144
+
69
145
  end
data/test/spec_urlmap.rb CHANGED
@@ -10,11 +10,11 @@ describe Rack::URLMap do
10
10
  'Content-Type' => 'text/plain'
11
11
  }, [""]]
12
12
  }
13
- map = Rack::URLMap.new({
13
+ map = Rack::Lint.new(Rack::URLMap.new({
14
14
  'http://foo.org/bar' => app,
15
15
  '/foo' => app,
16
16
  '/foo/bar' => app
17
- })
17
+ }))
18
18
 
19
19
  res = Rack::MockRequest.new(map).get("/")
20
20
  res.should.be.not_found
@@ -66,7 +66,7 @@ describe Rack::URLMap do
66
66
 
67
67
 
68
68
  it "dispatches hosts correctly" do
69
- map = Rack::URLMap.new("http://foo.org/" => lambda { |env|
69
+ map = Rack::Lint.new(Rack::URLMap.new("http://foo.org/" => lambda { |env|
70
70
  [200,
71
71
  { "Content-Type" => "text/plain",
72
72
  "X-Position" => "foo.org",
@@ -90,7 +90,7 @@ describe Rack::URLMap do
90
90
  "X-Position" => "default.org",
91
91
  "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
92
92
  }, [""]]}
93
- )
93
+ ))
94
94
 
95
95
  res = Rack::MockRequest.new(map).get("/")
96
96
  res.should.be.ok
@@ -124,7 +124,7 @@ describe Rack::URLMap do
124
124
  end
125
125
 
126
126
  should "be nestable" do
127
- map = Rack::URLMap.new("/foo" =>
127
+ map = Rack::Lint.new(Rack::URLMap.new("/foo" =>
128
128
  Rack::URLMap.new("/bar" =>
129
129
  Rack::URLMap.new("/quux" => lambda { |env|
130
130
  [200,
@@ -133,7 +133,7 @@ describe Rack::URLMap do
133
133
  "X-PathInfo" => env["PATH_INFO"],
134
134
  "X-ScriptName" => env["SCRIPT_NAME"],
135
135
  }, [""]]}
136
- )))
136
+ ))))
137
137
 
138
138
  res = Rack::MockRequest.new(map).get("/foo/bar")
139
139
  res.should.be.not_found
@@ -146,7 +146,7 @@ describe Rack::URLMap do
146
146
  end
147
147
 
148
148
  should "route root apps correctly" do
149
- map = Rack::URLMap.new("/" => lambda { |env|
149
+ map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
150
150
  [200,
151
151
  { "Content-Type" => "text/plain",
152
152
  "X-Position" => "root",
@@ -160,7 +160,7 @@ describe Rack::URLMap do
160
160
  "X-PathInfo" => env["PATH_INFO"],
161
161
  "X-ScriptName" => env["SCRIPT_NAME"]
162
162
  }, [""]]}
163
- )
163
+ ))
164
164
 
165
165
  res = Rack::MockRequest.new(map).get("/foo/bar")
166
166
  res.should.be.ok
@@ -188,7 +188,7 @@ describe Rack::URLMap do
188
188
  end
189
189
 
190
190
  should "not squeeze slashes" do
191
- map = Rack::URLMap.new("/" => lambda { |env|
191
+ map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
192
192
  [200,
193
193
  { "Content-Type" => "text/plain",
194
194
  "X-Position" => "root",
@@ -202,7 +202,7 @@ describe Rack::URLMap do
202
202
  "X-PathInfo" => env["PATH_INFO"],
203
203
  "X-ScriptName" => env["SCRIPT_NAME"]
204
204
  }, [""]]}
205
- )
205
+ ))
206
206
 
207
207
  res = Rack::MockRequest.new(map).get("/http://example.org/bar")
208
208
  res.should.be.ok
data/test/spec_utils.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require 'rack/utils'
3
3
  require 'rack/mock'
4
+ require 'timeout'
4
5
 
5
6
  describe Rack::Utils do
6
7
 
@@ -112,6 +113,14 @@ describe Rack::Utils do
112
113
  Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
113
114
  should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
114
115
  Rack::Utils.parse_query("foo%3Dbaz=bar").should.equal "foo=baz" => "bar"
116
+ Rack::Utils.parse_query("=").should.equal "" => ""
117
+ Rack::Utils.parse_query("=value").should.equal "" => "value"
118
+ Rack::Utils.parse_query("key=").should.equal "key" => ""
119
+ Rack::Utils.parse_query("&key&").should.equal "key" => nil
120
+ Rack::Utils.parse_query(";key;", ";,").should.equal "key" => nil
121
+ Rack::Utils.parse_query(",key,", ";,").should.equal "key" => nil
122
+ Rack::Utils.parse_query(";foo=bar,;", ";,").should.equal "foo" => "bar"
123
+ Rack::Utils.parse_query(",foo=bar;,", ";,").should.equal "foo" => "bar"
115
124
  end
116
125
 
117
126
  should "parse nested query strings correctly" do
@@ -188,7 +197,7 @@ describe Rack::Utils do
188
197
 
189
198
  lambda { Rack::Utils.parse_nested_query("x[y]=1&x[]=1") }.
190
199
  should.raise(TypeError).
191
- message.should.match /expected Array \(got [^)]*\) for param `x'/
200
+ message.should.match(/expected Array \(got [^)]*\) for param `x'/)
192
201
 
193
202
  lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y][][w]=2") }.
194
203
  should.raise(TypeError).
@@ -322,6 +331,11 @@ describe Rack::Utils do
322
331
  Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6
323
332
  end
324
333
 
334
+ should "should perform constant time string comparison" do
335
+ Rack::Utils.secure_compare('a', 'a').should.equal true
336
+ Rack::Utils.secure_compare('a', 'b').should.equal false
337
+ end
338
+
325
339
  should "return status code for integer" do
326
340
  Rack::Utils.status_code(200).should.equal 200
327
341
  end
@@ -356,6 +370,10 @@ describe Rack::Utils, "byte_range" do
356
370
  Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=499-499"},500).should.equal [(499..499)]
357
371
  end
358
372
 
373
+ should "parse several byte ranges" do
374
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-600,601-999"},1000).should.equal [(500..600),(601..999)]
375
+ end
376
+
359
377
  should "truncate byte ranges" do
360
378
  Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-999"},500).should.equal [(123..499)]
361
379
  Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=600-999"},500).should.equal []
@@ -0,0 +1 @@
1
+ another index!
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 4
9
- - 1
10
- version: 1.4.1
9
+ - 5
10
+ version: 1.4.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Christian Neukirchen
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-23 00:00:00 Z
18
+ date: 2013-02-08 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bacon
@@ -81,7 +81,7 @@ dependencies:
81
81
  requirements:
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
- hash: 1923831981
84
+ hash: 3904189667
85
85
  segments:
86
86
  - 1
87
87
  - 2
@@ -112,7 +112,7 @@ description: |
112
112
  servers, web frameworks, and software in between (the so-called
113
113
  middleware) into a single method call.
114
114
 
115
- Also see http://rack.rubyforge.org.
115
+ Also see http://rack.github.com/.
116
116
 
117
117
  email: chneukirchen@gmail.com
118
118
  executables:
@@ -124,7 +124,10 @@ extra_rdoc_files:
124
124
  - KNOWN-ISSUES
125
125
  files:
126
126
  - bin/rackup
127
+ - contrib/rack.png
128
+ - contrib/rack.svg
127
129
  - contrib/rack_logo.svg
130
+ - contrib/rdoc.css
128
131
  - example/lobster.ru
129
132
  - example/protectedlobster.rb
130
133
  - example/protectedlobster.ru
@@ -137,6 +140,7 @@ files:
137
140
  - lib/rack/auth/digest/request.rb
138
141
  - lib/rack/backports/uri/common_18.rb
139
142
  - lib/rack/backports/uri/common_192.rb
143
+ - lib/rack/backports/uri/common_193.rb
140
144
  - lib/rack/body_proxy.rb
141
145
  - lib/rack/builder.rb
142
146
  - lib/rack/cascade.rb
@@ -194,7 +198,14 @@ files:
194
198
  - test/builder/anything.rb
195
199
  - test/builder/comment.ru
196
200
  - test/builder/end.ru
201
+ - test/builder/line.ru
197
202
  - test/builder/options.ru
203
+ - test/cgi/assets/folder/test.js
204
+ - test/cgi/assets/fonts/font.eot
205
+ - test/cgi/assets/images/image.png
206
+ - test/cgi/assets/index.html
207
+ - test/cgi/assets/javascripts/app.js
208
+ - test/cgi/assets/stylesheets/app.css
198
209
  - test/cgi/lighttpd.conf
199
210
  - test/cgi/rackup_stub.rb
200
211
  - test/cgi/sample_rackup.ru
@@ -226,6 +237,7 @@ files:
226
237
  - test/multipart/webkit
227
238
  - test/rackup/config.ru
228
239
  - test/registering_handler/rack/handler/registering_myself.rb
240
+ - test/spec_auth.rb
229
241
  - test/spec_auth_basic.rb
230
242
  - test/spec_auth_digest.rb
231
243
  - test/spec_body_proxy.rb
@@ -272,6 +284,7 @@ files:
272
284
  - test/spec_urlmap.rb
273
285
  - test/spec_utils.rb
274
286
  - test/spec_webrick.rb
287
+ - test/static/another/index.html
275
288
  - test/static/index.html
276
289
  - test/testrequest.rb
277
290
  - test/unregistered_handler/rack/handler/unregistered.rb
@@ -282,7 +295,7 @@ files:
282
295
  - Rakefile
283
296
  - README.rdoc
284
297
  - SPEC
285
- homepage: http://rack.rubyforge.org
298
+ homepage: http://rack.github.com/
286
299
  licenses: []
287
300
 
288
301
  post_install_message:
@@ -311,11 +324,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
311
324
  requirements: []
312
325
 
313
326
  rubyforge_project: rack
314
- rubygems_version: 1.8.12
327
+ rubygems_version: 1.8.24
315
328
  signing_key:
316
329
  specification_version: 3
317
330
  summary: a modular Ruby webserver interface
318
331
  test_files:
332
+ - test/spec_auth.rb
319
333
  - test/spec_auth_basic.rb
320
334
  - test/spec_auth_digest.rb
321
335
  - test/spec_body_proxy.rb
@@ -362,3 +376,4 @@ test_files:
362
376
  - test/spec_urlmap.rb
363
377
  - test/spec_utils.rb
364
378
  - test/spec_webrick.rb
379
+ has_rdoc: